diff options
Diffstat (limited to 'WebKit/android')
19 files changed, 295 insertions, 104 deletions
diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp index f5b8a20..95673d7 100644 --- a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp @@ -775,7 +775,8 @@ bool FrameLoaderClientAndroid::canShowMIMEType(const String& mimeType) const { && m_frame->settings()->arePluginsEnabled() && PluginDatabase::installedPlugins()->isMIMETypeRegistered( mimeType)) || - DOMImplementation::isTextMIMEType(mimeType) || + (DOMImplementation::isTextMIMEType(mimeType) && + !mimeType.startsWith("text/vnd")) || DOMImplementation::isXMLMIMEType(mimeType)) return true; return false; diff --git a/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp b/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp index 2b2ad95..8872a52 100644 --- a/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp @@ -36,7 +36,7 @@ using namespace android; namespace WebCore { PassRefPtr<ResourceLoaderAndroid> ResourceLoaderAndroid::start( - ResourceHandle* handle, const ResourceRequest& request, FrameLoaderClient* client, bool isMainResource, bool isSync) + ResourceHandle* handle, const ResourceRequest& request, FrameLoaderClient* client, bool isMainResource, bool isSync, bool /*isPrivateBrowsing*/) { FrameLoaderClientAndroid* clientAndroid = static_cast<FrameLoaderClientAndroid*> (client); return clientAndroid->webFrame()->startLoadingResource(handle, request, isMainResource, isSync); diff --git a/WebKit/android/WebCoreSupport/WebRequest.cpp b/WebKit/android/WebCoreSupport/WebRequest.cpp index 4030160..9118baf 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.cpp +++ b/WebKit/android/WebCoreSupport/WebRequest.cpp @@ -49,7 +49,9 @@ namespace { const int kInitialReadBufSize = 32768; } -WebRequest::WebRequest(WebUrlLoaderClient* loader, WebResourceRequest webResourceRequest) : m_urlLoader(loader), m_request(0) +WebRequest::WebRequest(WebUrlLoaderClient* loader, WebResourceRequest webResourceRequest) + : m_urlLoader(loader) + , m_request(0) { GURL gurl(webResourceRequest.url()); m_request = new URLRequest(gurl, this); @@ -67,11 +69,11 @@ void WebRequest::finish(bool success) { if (success) { LoaderData* loaderData = new LoaderData(m_urlLoader); - callOnMainThread(WebUrlLoaderClient::didFinishLoading, loaderData); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::didFinishLoading, loaderData); } else { WebResponse webResponse(m_request.get()); LoaderData* loaderData = new LoaderData(m_urlLoader, webResponse); - callOnMainThread(WebUrlLoaderClient::didFail, loaderData); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::didFail, loaderData); } m_networkBuffer = 0; m_request = 0; @@ -82,13 +84,17 @@ void WebRequest::AppendBytesToUpload(const char* bytes, int bytesLen) m_request->AppendBytesToUpload(bytes, bytesLen); } -void WebRequest::start() +void WebRequest::start(bool isPrivateBrowsing) { // Handle data urls before we send it off to the http stack if (m_request->url().SchemeIs("data")) return handleDataURL(m_request->url()); - m_request->set_context(WebRequestContext::GetAndroidContext()); + if (!isPrivateBrowsing) + m_request->set_context(WebRequestContext::GetAndroidContext()); + else + m_request->set_context(WebRequestContext::GetAndroidPrivateBrowsingContext()); + m_request->Start(); } @@ -110,11 +116,11 @@ void WebRequest::handleDataURL(GURL url) // weburlloader_impl.cc WebResponse webResponse(url.spec(), mimeType, data->size(), charset, 200); LoaderData* loaderResponse = new LoaderData(m_urlLoader, webResponse); - callOnMainThread(WebUrlLoaderClient::didReceiveResponse, loaderResponse); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::didReceiveResponse, loaderResponse); if (!data->empty()) { LoaderData* loaderData = new LoaderData(m_urlLoader, data.leakPtr()); - callOnMainThread(WebUrlLoaderClient::didReceiveDataUrl, loaderData); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::didReceiveDataUrl, loaderData); } } else { // handle the failed case @@ -123,7 +129,6 @@ void WebRequest::handleDataURL(GURL url) finish(true); } - // Called upon a server-initiated redirect. The delegate may call the // request's Cancel method to prevent the redirect from being followed. // Since there may be multiple chained redirects, there may also be more @@ -146,7 +151,7 @@ void WebRequest::OnReceivedRedirect(URLRequest* newRequest, const GURL& newUrl, WebResponse webResponse(newRequest); webResponse.setUrl(newUrl.spec()); LoaderData* ld = new LoaderData(m_urlLoader, webResponse); - callOnMainThread(WebUrlLoaderClient::willSendRequest, ld); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::willSendRequest, ld); } else { // why would this happen? And what to do? } @@ -180,7 +185,7 @@ void WebRequest::OnResponseStarted(URLRequest* request) if (request && request->status().is_success()) { WebResponse webResponse(request); LoaderData* loaderData = new LoaderData(m_urlLoader, webResponse); - callOnMainThread(WebUrlLoaderClient::didReceiveResponse, loaderData); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::didReceiveResponse, loaderData); // Start reading the response startReading(); @@ -205,7 +210,7 @@ void WebRequest::startReading() // Read ok, forward buffer to webcore m_networkBuffer->AddRef(); LoaderData* loaderData = new LoaderData(m_urlLoader, m_networkBuffer.get(), bytesRead); - callOnMainThread(WebUrlLoaderClient::didReceiveData, loaderData); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::didReceiveData, loaderData); // m_networkBuffer->Release() on main thread m_networkBuffer = 0; } else if (m_request && m_request->status().is_io_pending()) { @@ -241,7 +246,7 @@ void WebRequest::OnReadCompleted(URLRequest* request, int bytesRead) m_networkBuffer->AddRef(); LoaderData* loaderData = new LoaderData(m_urlLoader, m_networkBuffer.get(), bytesRead); // m_networkBuffer->Release() on main thread - callOnMainThread(WebUrlLoaderClient::didReceiveData, loaderData); + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::didReceiveData, loaderData); m_networkBuffer = 0; // Get the rest of the data diff --git a/WebKit/android/WebCoreSupport/WebRequest.h b/WebKit/android/WebCoreSupport/WebRequest.h index 2bd86d8..9c9c830 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.h +++ b/WebKit/android/WebCoreSupport/WebRequest.h @@ -45,7 +45,7 @@ public: // Optional, but if used has to be called before start void AppendBytesToUpload(const char* bytes, int bytesLen); - void start(); + void start(bool isPrivateBrowsing); void cancel(); // From URLRequest::Delegate diff --git a/WebKit/android/WebCoreSupport/WebRequestContext.cpp b/WebKit/android/WebCoreSupport/WebRequestContext.cpp index e9ef24c..6b2fe1b 100644 --- a/WebKit/android/WebCoreSupport/WebRequestContext.cpp +++ b/WebKit/android/WebCoreSupport/WebRequestContext.cpp @@ -36,10 +36,14 @@ #include <net/http/http_cache.h> #include <net/http/http_network_layer.h> #include <net/proxy/proxy_service.h> +#include <wtf/text/CString.h> namespace { - // TODO: Get uastring from webcore - std::string userAgent("Mozilla/5.0 (Linux; U; Android 2.1; en-gb; Nexus One Build/ERE21) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17"); +std::string userAgent("Mozilla/5.0 (Linux; U; Android 2.1; en-gb; Nexus One Build/ERE21) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17"); +std::string acceptLanguage(""); + +Lock userAgentLock; +Lock acceptLanguageLock; } namespace android { @@ -48,17 +52,39 @@ std::string* WebRequestContext::s_dataDirectory(0); WebRequestContext::WebRequestContext() { + // Also hardcoded in FrameLoader.java + accept_charset_ = "utf-8, iso-8859-1, utf-16, *;q=0.7"; } WebRequestContext::~WebRequestContext() { } +void WebRequestContext::SetUserAgent(WTF::String string) +{ + AutoLock aLock(userAgentLock); + userAgent = string.utf8().data(); + userAgent.append(" alternate http"); +} + const std::string& WebRequestContext::GetUserAgent(const GURL& url) const { + AutoLock aLock(userAgentLock); return userAgent; } +void WebRequestContext::SetAcceptLanguage(WTF::String string) +{ + AutoLock aLock(acceptLanguageLock); + acceptLanguage = string.utf8().data(); +} + +const std::string& WebRequestContext::GetAcceptLanguage() const +{ + AutoLock aLock(acceptLanguageLock); + return acceptLanguage; +} + const std::string* WebRequestContext::GetDataDirectory() { if (!s_dataDirectory) { @@ -77,28 +103,44 @@ const std::string* WebRequestContext::GetDataDirectory() return s_dataDirectory; } +WebRequestContext* WebRequestContext::GetAndroidContextForPath(const char* cookieFilename, const char* cacheFilename) +{ + std::string cookieString(*GetDataDirectory()); + cookieString.append(cookieFilename); + FilePath cookiePath(cookieString.c_str()); + std::string cacheString(*GetDataDirectory()); + cacheString.append(cacheFilename); + FilePath cachePath(cacheString.c_str()); + + scoped_refptr<WebRequestContext> androidContext = new WebRequestContext(); + androidContext->host_resolver_ = net::CreateSystemHostResolver(0); + scoped_refptr<base::MessageLoopProxy> cacheMessageLoopProxy = base::MessageLoopProxy::CreateForCurrentThread(); + // Todo: check if the context takes ownership of the cache + net::HttpCache::DefaultBackend* defaultBackend = new net::HttpCache::DefaultBackend(net::DISK_CACHE, cachePath, 20 * 1024 * 1024, cacheMessageLoopProxy); + androidContext->http_transaction_factory_ = new net::HttpCache(androidContext->host_resolver(), net::ProxyService::CreateNull(), net::SSLConfigService::CreateSystemSSLConfigService(), 0, 0, 0, defaultBackend); + + scoped_refptr<SQLitePersistentCookieStore> cookieDb = new SQLitePersistentCookieStore(cookiePath); + androidContext->cookie_store_ = new net::CookieMonster(cookieDb.get(), 0); + + return androidContext.release(); +} + WebRequestContext* WebRequestContext::GetAndroidContext() { static scoped_refptr<WebRequestContext> androidContext(0); + if (!androidContext) + androidContext = GetAndroidContextForPath("/chromecookies.db", "/chromecache"); + return androidContext; +} + +WebRequestContext* WebRequestContext::GetAndroidPrivateBrowsingContext() +{ + static scoped_refptr<WebRequestContext> androidContext(0); if (!androidContext) { - std::string cookieString(*GetDataDirectory()); - cookieString.append("/chromecookies.db"); - FilePath cookiePath(cookieString.c_str()); - std::string cacheString(*GetDataDirectory()); - cacheString.append("/chromecache"); - FilePath cachePath(cacheString.c_str()); - - androidContext = new WebRequestContext(); - androidContext->host_resolver_ = net::CreateSystemHostResolver(0); - scoped_refptr<base::MessageLoopProxy> cacheMessageLoopProxy = base::MessageLoopProxy::CreateForCurrentThread(); - // Todo: check if the context takes ownership of the cache - net::HttpCache::DefaultBackend* defaultBackend = new net::HttpCache::DefaultBackend(net::DISK_CACHE, cachePath, 20 * 1024 * 1024, cacheMessageLoopProxy); - androidContext->http_transaction_factory_ = new net::HttpCache(androidContext->host_resolver(), net::ProxyService::CreateNull(), net::SSLConfigService::CreateSystemSSLConfigService(), 0, 0, 0, defaultBackend); - - scoped_refptr<SQLitePersistentCookieStore> cookieDb = new SQLitePersistentCookieStore(cookiePath); - androidContext->cookie_store_ = new net::CookieMonster(cookieDb.get(), 0); + // TODO: Where is the right place to put the temporary db? Should it be + // kept in memory? + androidContext = GetAndroidContextForPath("/chromecookies_private.db", "/chromecache_private"); } - return androidContext; } diff --git a/WebKit/android/WebCoreSupport/WebRequestContext.h b/WebKit/android/WebCoreSupport/WebRequestContext.h index 0ff081c..a1f7973 100644 --- a/WebKit/android/WebCoreSupport/WebRequestContext.h +++ b/WebKit/android/WebCoreSupport/WebRequestContext.h @@ -31,22 +31,32 @@ // a subclass of a chrome class. #if USE(CHROME_NETWORK_STACK) -#include "net/http/http_cache.h" -#include "net/url_request/url_request_context.h" +#include "PlatformString.h" + +#include <net/http/http_cache.h> +#include <net/url_request/url_request_context.h> namespace android { class WebRequestContext : public URLRequestContext { public: virtual const std::string& GetUserAgent(const GURL& url) const; + virtual const std::string& GetAcceptLanguage() const; static WebRequestContext* GetAndroidContext(); + static WebRequestContext* GetAndroidPrivateBrowsingContext(); + + static void SetUserAgent(WTF::String); + static void SetAcceptLanguage(WTF::String); + private: static const std::string* GetDataDirectory(); + static WebRequestContext* GetAndroidContextForPath(const char* cookiePath, const char* cachePath); WebRequestContext(); ~WebRequestContext(); // Caching this query from java static std::string* s_dataDirectory; + static std::string* s_userAgent; }; } // namespace android diff --git a/WebKit/android/WebCoreSupport/WebUrlLoader.cpp b/WebKit/android/WebCoreSupport/WebUrlLoader.cpp index 9df58e4..4b815c6 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoader.cpp +++ b/WebKit/android/WebCoreSupport/WebUrlLoader.cpp @@ -42,10 +42,10 @@ WebUrlLoader::~WebUrlLoader() { } -PassRefPtr<WebUrlLoader> WebUrlLoader::start(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest, bool isSync) +PassRefPtr<WebUrlLoader> WebUrlLoader::start(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest, bool isSync, bool isPrivateBrowsing) { RefPtr<WebUrlLoader> loader = WebUrlLoader::create(resourceHandle, resourceRequest); - loader->m_loaderClient->start(isSync); + loader->m_loaderClient->start(isSync, isPrivateBrowsing); return loader.release(); } @@ -69,9 +69,9 @@ namespace WebCore { // static // TODO: Implement sync requests PassRefPtr<ResourceLoaderAndroid> ResourceLoaderAndroid::start(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest, - FrameLoaderClient* /*client*/, bool /*isMainResource*/, bool isSync) + FrameLoaderClient* /*client*/, bool /*isMainResource*/, bool isSync, bool isPrivateBrowsing) { - return android::WebUrlLoader::start(resourceHandle, resourceRequest, isSync); + return android::WebUrlLoader::start(resourceHandle, resourceRequest, isSync, isPrivateBrowsing); } // static diff --git a/WebKit/android/WebCoreSupport/WebUrlLoader.h b/WebKit/android/WebCoreSupport/WebUrlLoader.h index 167bdc0..c465b66 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoader.h +++ b/WebKit/android/WebCoreSupport/WebUrlLoader.h @@ -36,7 +36,7 @@ class WebUrlLoaderClient; class WebUrlLoader : public ResourceLoaderAndroid { public: virtual ~WebUrlLoader(); - static PassRefPtr<WebUrlLoader> start(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, bool sync); + static PassRefPtr<WebUrlLoader> start(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, bool sync, bool isPrivateBrowsing); virtual void cancel(); virtual void downloadFile() {} // Not implemented yet diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp index bfb8eb7..e3ee14c 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp @@ -33,6 +33,8 @@ #include "WebRequest.h" #include "WebResourceRequest.h" +#include <base/condition_variable.h> +#include <base/lock.h> #include <base/thread.h> #include <net/base/io_buffer.h> @@ -66,12 +68,21 @@ base::Thread* WebUrlLoaderClient::ioThread() return networkThread; } +Lock* WebUrlLoaderClient::syncLock() { + static Lock s_syncLock; + return &s_syncLock; +} + +ConditionVariable* WebUrlLoaderClient::syncCondition() { + static ConditionVariable s_syncCondition(syncLock()); + return &s_syncCondition; +} + WebUrlLoaderClient::~WebUrlLoaderClient() { base::Thread* thread = ioThread(); if (thread) thread->message_loop()->ReleaseSoon(FROM_HERE, m_request); - } bool WebUrlLoaderClient::isActive() const @@ -85,7 +96,10 @@ bool WebUrlLoaderClient::isActive() const } WebUrlLoaderClient::WebUrlLoaderClient(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest) - : m_resourceHandle(resourceHandle), m_cancelling(false) + : m_resourceHandle(resourceHandle) + , m_cancelling(false) + , m_sync(false) + , m_finished(false) { WebResourceRequest webResourceRequest(resourceRequest); @@ -129,15 +143,40 @@ WebUrlLoaderClient::WebUrlLoaderClient(WebCore::ResourceHandle* resourceHandle, } } -bool WebUrlLoaderClient::start(bool /*sync*/) +bool WebUrlLoaderClient::start(bool sync, bool isPrivateBrowsing) { base::Thread* thread = ioThread(); - if (thread) { - thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::start)); - return true; + if (!thread) { + return false; } - return false; + m_sync = sync; + if (m_sync) { + AutoLock autoLock(*syncLock()); + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::start, isPrivateBrowsing)); + + // Run callbacks until the queue is exhausted and m_finished is true. + while(!m_finished) { + while (!m_queue.empty()) { + Callback& callback = m_queue.front(); + CallbackFunction* function = callback.a; + void* context = callback.b; + (*function)(context); + m_queue.pop_front(); + } + if (m_queue.empty() && !m_finished) { + syncCondition()->Wait(); + } + } + + // This may be the last reference to us, so we may be deleted now. + // Don't access any more member variables after releasing this reference. + m_resourceHandle = 0; + } else { + // Asynchronous start. + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::start, isPrivateBrowsing)); + } + return true; } void WebUrlLoaderClient::cancel() @@ -151,9 +190,26 @@ void WebUrlLoaderClient::cancel() void WebUrlLoaderClient::finish() { - // This will probably cause this to be deleted as we are the only one holding a reference to - // m_resourceHandle, and it is holding the only reference to this. - m_resourceHandle = 0; + m_finished = true; + if (!m_sync) { + // This is the last reference to us, so we will be deleted now. + // We only release the reference here if start() was called asynchronously! + m_resourceHandle = 0; + } +} + +// This is called from the IO thread, and dispatches the callback to the main thread. +void WebUrlLoaderClient::maybeCallOnMainThread(CallbackFunction* function, void* context) { + if (m_sync) { + AutoLock autoLock(*syncLock()); + if (m_queue.empty()) { + syncCondition()->Broadcast(); + } + m_queue.push_back(Callback(function, context)); + } else { + // Let WebKit handle it. + callOnMainThread(function, context); + } } // Response methods diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h index 399df08..a761f15 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h @@ -31,7 +31,12 @@ #include "WebUrlLoader.h" #include <base/ref_counted.h> +#include <base/tuple.h> #include <string> +#include <deque> + +class Lock; +class ConditionVariable; namespace base { class Thread; @@ -58,12 +63,18 @@ public: ~WebUrlLoaderClient(); // Called from WebCore, will be forwarded to the IO thread - bool start(bool sync); + bool start(bool sync, bool isPrivateBrowsing); void cancel(); void downloadFile(); void pauseLoad(bool pause) {} // Android method, does nothing for now - // Called by WebRequest, should be forwarded to WebCore + typedef void CallbackFunction(void*); + + // This is called from the IO thread, and dispatches the callback to the main thread. + // (For asynchronous calls, we just delegate to WebKit's callOnMainThread.) + void maybeCallOnMainThread(CallbackFunction*, void* context); + + // Called by WebRequest (using maybeCallOnMainThread), should be forwarded to WebCore. static void didReceiveResponse(void*); static void didReceiveData(void*); static void didReceiveDataUrl(void*); @@ -75,6 +86,8 @@ private: void finish(); RefPtr<WebCore::ResourceHandle> m_resourceHandle; bool m_cancelling; + bool m_sync; + volatile bool m_finished; // Not an OwnPtr since it should be deleted on another thread WebRequest* m_request; @@ -84,9 +97,20 @@ private: // Check if a request is active bool isActive() const; + + // Mutex and condition variable used for synchronous requests. + // Note that these are static. This works because there's only one main thread. + static Lock* syncLock(); + static ConditionVariable* syncCondition(); + + typedef Tuple2<CallbackFunction*, void*> Callback; + typedef std::deque<Callback> CallbackQueue; + + // Queue of callbacks to be executed by the main thread. Must only be accessed inside mutex. + CallbackQueue m_queue; }; -// A struct to send more than one thing in a void*, needed for callOnMainThread +// A struct to send more than one thing in a void*, needed for maybeCallOnMainThread struct LoaderData { net::IOBuffer* buffer; WebUrlLoaderClient* loader; diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index 10c8439..868233a 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -532,7 +532,12 @@ WebFrame::loadStarted(WebCore::Frame* frame) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - const WebCore::KURL& url = frame->loader()->activeDocumentLoader()->url(); + // activeDocumentLoader() can return null. + DocumentLoader* documentLoader = frame->loader()->activeDocumentLoader(); + if (documentLoader == NULL) + return; + + const WebCore::KURL& url = documentLoader->url(); if (url.isEmpty()) return; LOGV("::WebCore:: loadStarted %s", url.string().ascii().data()); @@ -598,8 +603,14 @@ WebFrame::didFinishLoad(WebCore::Frame* frame) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif JNIEnv* env = getJNIEnv(); + + // activeDocumentLoader() can return null. WebCore::FrameLoader* loader = frame->loader(); - const WebCore::KURL& url = loader->activeDocumentLoader()->url(); + DocumentLoader* documentLoader = loader->activeDocumentLoader(); + if (documentLoader == NULL) + return; + + const WebCore::KURL& url = documentLoader->url(); if (url.isEmpty()) return; LOGV("::WebCore:: didFinishLoad %s", url.string().ascii().data()); diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp index f389a39..9b84409 100644 --- a/WebKit/android/jni/WebSettings.cpp +++ b/WebKit/android/jni/WebSettings.cpp @@ -48,6 +48,7 @@ #if USE(V8) #include "WorkerContextExecutionProxy.h" #endif +#include "WebRequestContext.h" #include <JNIHelp.h> #include <utils/misc.h> @@ -76,6 +77,7 @@ struct FieldIds { "Ljava/lang/String;"); mUserAgent = env->GetFieldID(clazz, "mUserAgent", "Ljava/lang/String;"); + mAcceptLanguage = env->GetFieldID(clazz, "mAcceptLanguage", "Ljava/lang/String;"); mMinimumFontSize = env->GetFieldID(clazz, "mMinimumFontSize", "I"); mMinimumLogicalFontSize = env->GetFieldID(clazz, "mMinimumLogicalFontSize", "I"); mDefaultFontSize = env->GetFieldID(clazz, "mDefaultFontSize", "I"); @@ -130,6 +132,7 @@ struct FieldIds { LOG_ASSERT(mFantasyFontFamily, "Could not find field mFantasyFontFamily"); LOG_ASSERT(mDefaultTextEncoding, "Could not find field mDefaultTextEncoding"); LOG_ASSERT(mUserAgent, "Could not find field mUserAgent"); + LOG_ASSERT(mAcceptLanguage, "Could not find field mAcceptLanguage"); LOG_ASSERT(mMinimumFontSize, "Could not find field mMinimumFontSize"); LOG_ASSERT(mMinimumLogicalFontSize, "Could not find field mMinimumLogicalFontSize"); LOG_ASSERT(mDefaultFontSize, "Could not find field mDefaultFontSize"); @@ -177,6 +180,7 @@ struct FieldIds { jfieldID mFantasyFontFamily; jfieldID mDefaultTextEncoding; jfieldID mUserAgent; + jfieldID mAcceptLanguage; jfieldID mMinimumFontSize; jfieldID mMinimumLogicalFontSize; jfieldID mDefaultFontSize; @@ -295,6 +299,11 @@ public: str = (jstring)env->GetObjectField(obj, gFieldIds->mUserAgent); WebFrame::getWebFrame(pFrame)->setUserAgent(to_string(env, str)); +#if USE(CHROME_NETWORK_STACK) + WebRequestContext::SetUserAgent(to_string(env, str)); + str = (jstring)env->GetObjectField(obj, gFieldIds->mAcceptLanguage); + WebRequestContext::SetAcceptLanguage(to_string(env, str)); +#endif jint size = env->GetIntField(obj, gFieldIds->mMinimumFontSize); s->setMinimumFontSize(size); diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 1ed885a..6cd1280 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -2360,7 +2360,8 @@ void WebViewCore::touchUp(int touchGeneration, // Return the RenderLayer for the given RenderObject only if the layer is // composited and it contains a scrollable content layer. -static WebCore::RenderLayer* getLayerFromRenderer(WebCore::RenderObject* renderer) +static WebCore::RenderLayer* getLayerFromRenderer( + WebCore::RenderObject* renderer, LayerAndroid** aLayer) { if (!renderer) return 0; @@ -2371,9 +2372,10 @@ static WebCore::RenderLayer* getLayerFromRenderer(WebCore::RenderObject* rendere static_cast<GraphicsLayerAndroid*>(layer->backing()->graphicsLayer()); if (!graphicsLayer) return 0; - LayerAndroid* aLayer = graphicsLayer->contentLayer(); - if (!aLayer || !aLayer->contentIsScrollable()) + LayerAndroid* layerAndroid = graphicsLayer->contentLayer(); + if (!layerAndroid || !layerAndroid->contentIsScrollable()) return 0; + *aLayer = layerAndroid; return layer; } @@ -2381,34 +2383,27 @@ static WebCore::RenderLayer* getLayerFromRenderer(WebCore::RenderObject* rendere // done so that the node is visible when it is clicked. static void scrollLayer(WebCore::RenderObject* renderer, WebCore::IntPoint* pos) { - WebCore::RenderLayer* layer = getLayerFromRenderer(renderer); + LayerAndroid* aLayer; + WebCore::RenderLayer* layer = getLayerFromRenderer(renderer, &aLayer); if (!layer) return; WebCore::IntRect absBounds = renderer->absoluteBoundingBoxRect(); - WebCore::IntRect layerBounds = layer->absoluteBoundingBox(); + // Do not include the outline when moving the node's bounds. + WebCore::IntRect layerBounds = layer->renderer()->absoluteBoundingBoxRect(); // Move the node's bounds into the layer's coordinates. absBounds.move(-layerBounds.x(), -layerBounds.y()); + int diffX = layer->scrollXOffset(); + int diffY = layer->scrollYOffset(); // Scroll the layer to the node's position. The false parameters tell the // layer not to invalidate. - layer->scrollToOffset(absBounds.x(), absBounds.y(), false, false); + layer->scrollToOffset(absBounds.x(), absBounds.y(), false, true); + diffX = layer->scrollXOffset() - diffX; + diffY = layer->scrollYOffset() - diffY; // Update the mouse position to the layer offset. - pos->move(-layer->scrollXOffset(), -layer->scrollYOffset()); -} - -static void restoreScrolledLayer(WebCore::RenderObject* renderer, - WebCore::IntPoint* pos) -{ - WebCore::RenderLayer* layer = getLayerFromRenderer(renderer); - if (!layer) - return; - // Move the mouse position back to it's original position. - pos->move(layer->scrollXOffset(), layer->scrollYOffset()); - - // Scroll the layer back to 0,0. - layer->scrollToOffset(0, 0, false, false); + pos->move(-diffX, -diffY); } // Common code for both clicking with the trackball and touchUp @@ -2503,13 +2498,24 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node } else { requestKeyboard(false); } - } else if (focusNode->isContentEditable()) { - setFocusControllerActive(framePtr, true); - requestKeyboard(true); + } else { + // If the focusNode is contentEditable, show the keyboard and enable + // the focus controller so the user can type. Otherwise hide the + // keyboard and disable the focus controller because no text input + // is needed. + bool keyboard = focusNode->isContentEditable(); + setFocusControllerActive(framePtr, keyboard); + if (keyboard) { + requestKeyboard(true); + } else { + clearTextEntry(); + } } + } else { + // There is no focusNode, so the keyboard is not needed. + setFocusControllerActive(framePtr, false); + clearTextEntry(); } - if (nodePtr && valid) - restoreScrolledLayer(nodePtr->renderer(), &m_mousePos); return handled; } diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index e76c729..c05395c 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -915,7 +915,7 @@ static bool checkForPluginViewThatWantsFocus(RenderObject* renderer) { #if USE(ACCELERATED_COMPOSITING) static void AddLayer(CachedFrame* frame, size_t index, const IntPoint& location, - int id) + const IntPoint& scroll, int id) { DBG_NAV_LOGD("frame=%p index=%d loc=(%d,%d) id=%d", frame, index, location.x(), location.y(), id); @@ -923,6 +923,7 @@ static void AddLayer(CachedFrame* frame, size_t index, const IntPoint& location, cachedLayer.reset(); cachedLayer.setCachedNodeIndex(index); cachedLayer.setOffset(location); + cachedLayer.setScrollOffset(scroll); cachedLayer.setUniqueId(id); frame->add(cachedLayer); } @@ -1063,12 +1064,16 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, TrackLayer(layerTracker, nodeRenderer, lastChild, globalOffsetX, globalOffsetY); size_t size = tracker.size(); - const LayerAndroid* layer = layerTracker.last().mLayer; + LayerAndroid* layer = layerTracker.last().mLayer; if (layer) { int id = layer->uniqueId(); - IntPoint loc = nodeRenderer-> - absoluteBoundingBoxRect().location(); + const RenderLayer* renderLayer = + layerTracker.last().mRenderLayer; + IntPoint loc(SkScalarRound(layer->getPosition().fX), + SkScalarRound(layer->getPosition().fY)); loc.move(globalOffsetX, globalOffsetY); + IntPoint scroll(renderLayer->scrollXOffset(), + renderLayer->scrollYOffset()); // if this is a child of a CachedNode, add a layer size_t limit = cachedFrame->layerCount() == 0 ? 0 : cachedFrame->lastLayer()->cachedNodeIndex(); @@ -1084,7 +1089,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, CachedNode* trackedNode = cachedFrame->getIndex(index); trackedNode->setIsInLayer(true); trackedNode->setIsUnclipped(true); - AddLayer(cachedFrame, index, loc, id); + AddLayer(cachedFrame, index, loc, scroll, id); } } } @@ -1327,6 +1332,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, LayerAndroid* layer = layerTracker.last().mLayer; if (layer) { const IntRect& layerClip = layerTracker.last().mBounds; + const RenderLayer* renderLayer = layerTracker.last().mRenderLayer; if (!layer->contentIsScrollable() && !layerClip.isEmpty() && !cachedNode.clip(layerClip)) { DBG_NAV_LOGD("skipped on layer clip %d", cacheIndex); @@ -1334,8 +1340,10 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, } isInLayer = true; isUnclipped = true; // assume that layers do not have occluded nodes + IntPoint scroll(renderLayer->scrollXOffset(), + renderLayer->scrollYOffset()); AddLayer(cachedFrame, cachedFrame->size(), layerClip.location(), - layer->uniqueId()); + scroll, layer->uniqueId()); } #endif cachedNode.setNavableRects(); @@ -2838,7 +2846,8 @@ void CacheBuilder::TrackLayer(WTF::Vector<LayerTracker>& layerTracker, layerTracker.grow(layerTracker.size() + 1); LayerTracker& indexTracker = layerTracker.last(); indexTracker.mLayer = aLayer; - indexTracker.mBounds = nodeRenderer->absoluteBoundingBoxRect(); + indexTracker.mRenderLayer = layer; + indexTracker.mBounds = IntRect(FloatRect(aLayer->bounds())); indexTracker.mBounds.move(offsetX, offsetY); indexTracker.mLastChild = lastChild ? OneAfter(lastChild) : 0; DBG_NAV_LOGD("layer=%p [%d] bounds=(%d,%d,w=%d,h=%d)", aLayer, diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h index 5324187..d19e0c9 100644 --- a/WebKit/android/nav/CacheBuilder.h +++ b/WebKit/android/nav/CacheBuilder.h @@ -198,6 +198,7 @@ private: }; struct LayerTracker : Tracker { LayerAndroid* mLayer; + RenderLayer* mRenderLayer; IntRect mBounds; }; struct TabIndexTracker : Tracker { diff --git a/WebKit/android/nav/CachedLayer.cpp b/WebKit/android/nav/CachedLayer.cpp index 9c7d59b..c4293a5 100644 --- a/WebKit/android/nav/CachedLayer.cpp +++ b/WebKit/android/nav/CachedLayer.cpp @@ -49,6 +49,10 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root, // First, remove the original offset from the bounds. temp.move(-mOffset.x(), -mOffset.y()); + // Now, add in the original scroll position. This moves the node to the + // original location within the layer. + temp.move(mScrollOffset.x(), mScrollOffset.y()); + // Next, add in the new position of the layer (could be different due to a // fixed position layer). const FloatPoint& position = aLayer->getPosition(); @@ -72,12 +76,17 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root, DBG_NAV_LOGD("root=%p aLayer=%p [%d]" " bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g)" + " pos=(%f,%f)" " offset=(%d,%d) clip=(%d,%d,w=%d,h=%d)" + " scroll=(%d,%d) origScroll=(%d,%d)" " result=(%d,%d,w=%d,h=%d)", root, aLayer, aLayer->uniqueId(), bounds.x(), bounds.y(), bounds.width(), bounds.height(), - translation.x(), translation.y(), mOffset.x(), mOffset.y(), + translation.x(), translation.y(), position.x(), position.y(), + mOffset.x(), mOffset.y(), clip.x(), clip.y(), clip.width(), clip.height(), + SkScalarRound(scroll.fX), SkScalarRound(scroll.fY), + mScrollOffset.x(), mScrollOffset.y(), result.x(), result.y(), result.width(), result.height()); return result; } @@ -104,6 +113,9 @@ IntRect CachedLayer::unadjustBounds(const LayerAndroid* root, // Move it back to the original offset. temp.move(mOffset.x(), mOffset.y()); + + // Move the bounds by the original scroll. + temp.move(-mScrollOffset.x(), -mScrollOffset.y()); return temp; } @@ -122,6 +134,10 @@ IntRect CachedLayer::localBounds(const LayerAndroid* root, // Remove the original offset from the bounds. temp.move(-mOffset.x(), -mOffset.y()); + // We add in the original scroll position in order to position the node + // relative to the current internal scroll position. + temp.move(mScrollOffset.x(), mScrollOffset.y()); + const LayerAndroid* aLayer = layer(root); if (aLayer) { // Move the bounds by the scroll position of the layer. @@ -134,7 +150,12 @@ IntRect CachedLayer::localBounds(const LayerAndroid* root, temp.intersect(IntRect(aLayer->foregroundClip())); } - return enclosingIntRect(temp); + DBG_NAV_LOGD("bounds=(%d,%d,w=%d,h=%d) offset=(%d,%d)" + " result=(%d,%d,w=%d,h=%d)", bounds.x(), bounds.y(), + bounds.width(), bounds.height(), mOffset.x(), mOffset.y(), + temp.x(), temp.y(), temp.width(), temp.height()); + + return temp; } SkPicture* CachedLayer::picture(const LayerAndroid* root) const diff --git a/WebKit/android/nav/CachedLayer.h b/WebKit/android/nav/CachedLayer.h index 8bfe922..0a56ea1 100644 --- a/WebKit/android/nav/CachedLayer.h +++ b/WebKit/android/nav/CachedLayer.h @@ -58,12 +58,18 @@ public: void reset() { mLayer = 0; } void setCachedNodeIndex(int index) { mCachedNodeIndex = index; } void setOffset(const IntPoint& offset) { mOffset = offset; } + void setScrollOffset(const IntPoint& scrollOffset) { + mScrollOffset = scrollOffset; + } void setUniqueId(int uniqueId) { mUniqueId = uniqueId; } int uniqueId() const { return mUniqueId; } private: int mCachedNodeIndex; mutable const LayerAndroid* mLayer; + // mOffset and mScrollOffset are the position and scroll offset of the + // layer when recorded by the nav cache. IntPoint mOffset; + IntPoint mScrollOffset; int mUniqueId; #if DUMP_NAV_CACHE diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h index 2853241..a6420f9 100644 --- a/WebKit/android/nav/CachedRoot.h +++ b/WebKit/android/nav/CachedRoot.h @@ -96,7 +96,10 @@ public: void setTextGeneration(int textGeneration) { mTextGeneration = textGeneration; } void setMaxScroll(int x, int y) { mMaxXScroll = x; mMaxYScroll = y; } void setPicture(SkPicture* picture) { mPicture = picture; } - void setRootLayer(WebCore::LayerAndroid* layer) { mRootLayer = layer; } + void setRootLayer(WebCore::LayerAndroid* layer) { + mRootLayer = layer; + resetLayers(); + } void setScrollOnly(bool state) { mScrollOnly = state; } void setSelection(int start, int end) { mSelectionStart = start; mSelectionEnd = end; } void setupScrolledBounds() const { mScrolledBounds = mViewBounds; } diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index efaa509..2132957 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -105,7 +105,6 @@ enum DrawExtras { // keep this in sync with WebView.java struct JavaGlue { jweak m_obj; jmethodID m_calcOurContentVisibleRectF; - jmethodID m_clearTextEntry; jmethodID m_overrideLoading; jmethodID m_scrollBy; jmethodID m_sendMoveFocus; @@ -141,7 +140,6 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) : m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView); m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z"); m_javaGlue.m_calcOurContentVisibleRectF = GetJMethod(env, clazz, "calcOurContentVisibleRectF", "(Landroid/graphics/RectF;)V"); - m_javaGlue.m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "(Z)V"); m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V"); m_javaGlue.m_sendMoveFocus = GetJMethod(env, clazz, "sendMoveFocus", "(II)V"); m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V"); @@ -222,15 +220,6 @@ void hideCursor() viewInvalidate(); } -void clearTextEntry() -{ - DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue.object(env).get(), - m_javaGlue.m_clearTextEntry, true); - checkException(env); -} - #if DUMP_NAV_CACHE void debugDump() { @@ -893,7 +882,6 @@ bool motionUp(int x, int y, int slop) sendMotionUp(frame ? (WebCore::Frame*) frame->framePointer() : 0, 0, x, y); viewInvalidate(); - clearTextEntry(); return pageScrolled; } DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result, @@ -914,7 +902,6 @@ bool motionUp(int x, int y, int slop) } viewInvalidate(); if (!result->isTextInput()) { - clearTextEntry(); if (!result->isSelect() && !result->isContentEditable()) setFollowedLink(true); if (syntheticLink) |
