diff options
author | Iain Merrick <husky@google.com> | 2010-08-23 17:35:30 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-09-20 12:14:03 +0100 |
commit | d4ff0cc91b5eb975d563f355f9f4c7358e0e2c06 (patch) | |
tree | 69dda182d1890032def251c6888fcfb97d4d5135 /WebKit | |
parent | f8230805249e7f0956d00204d2e610208efe5ad9 (diff) | |
download | external_webkit-d4ff0cc91b5eb975d563f355f9f4c7358e0e2c06.zip external_webkit-d4ff0cc91b5eb975d563f355f9f4c7358e0e2c06.tar.gz external_webkit-d4ff0cc91b5eb975d563f355f9f4c7358e0e2c06.tar.bz2 |
HTTP auth for Chromium HTTP stack (C++ side)
On receiving an auth request:
- WebRequest (on the IO thread) sends a message to WebUrlLoaderClient
- WebUrlLoaderClient (webkit thread) calls WebCoreFrameBridge.
- WebCoreFrameBridge makes a JNI call to BrowserFrame.java.
Each JNI call has a WebUrlLoaderClient pointer, cast to an int.
We use this to recover the context when we're called back, and
dispatch a message back to WebRequest.
Corresponding Java change: https://android-git.corp.google.com/g/63762
Change-Id: Ieb72f2eaa996a55916c987859f47f6dacf92e06c
Diffstat (limited to 'WebKit')
-rw-r--r-- | WebKit/android/WebCoreSupport/ChromiumIncludes.h | 2 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequest.cpp | 22 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequest.h | 4 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebResponse.h | 2 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp | 48 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoaderClient.h | 13 | ||||
-rw-r--r-- | WebKit/android/jni/WebCoreFrameBridge.cpp | 68 | ||||
-rw-r--r-- | WebKit/android/jni/WebCoreFrameBridge.h | 4 |
8 files changed, 157 insertions, 6 deletions
diff --git a/WebKit/android/WebCoreSupport/ChromiumIncludes.h b/WebKit/android/WebCoreSupport/ChromiumIncludes.h index 1a69ff1..635c4da 100644 --- a/WebKit/android/WebCoreSupport/ChromiumIncludes.h +++ b/WebKit/android/WebCoreSupport/ChromiumIncludes.h @@ -50,9 +50,11 @@ #include <base/message_loop_proxy.h> #include <base/ref_counted.h> #include <base/string_util.h> +#include <base/sys_string_conversions.h> #include <base/thread.h> #include <base/tuple.h> #include <chrome/browser/net/sqlite_persistent_cookie_store.h> +#include <net/base/auth.h> #include <net/base/cookie_monster.h> #include <net/base/data_url.h> #include <net/base/io_buffer.h> diff --git a/WebKit/android/WebCoreSupport/WebRequest.cpp b/WebKit/android/WebCoreSupport/WebRequest.cpp index 10b0cc7..e440181 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.cpp +++ b/WebKit/android/WebCoreSupport/WebRequest.cpp @@ -295,9 +295,11 @@ void WebRequest::OnReceivedRedirect(URLRequest* newRequest, const GURL& newUrl, // of On* callbacks. void WebRequest::OnAuthRequired(URLRequest* request, net::AuthChallengeInfo* authInfo) { - // TODO: This is the default action, have to implement getting the - // username and password from webkit - request->CancelAuth(); + ASSERT(m_loadState == Started, "OnAuthRequired called on a WebRequest not in STARTED state (state=%d)", m_loadState); + + LoaderData* ld = new LoaderData(m_urlLoader); + ld->authChallengeInfo = authInfo; + m_urlLoader->maybeCallOnMainThread(WebUrlLoaderClient::authRequired, ld); } // After calling Start(), the delegate will receive an OnResponseStarted @@ -323,6 +325,20 @@ void WebRequest::OnResponseStarted(URLRequest* request) } } +void WebRequest::setAuth(const std::wstring& username, const std::wstring& password) +{ + ASSERT(m_loadState == Started, "setAuth called on a WebRequest not in STARTED state (state=%d)", m_loadState); + + m_request->SetAuth(username, password); +} + +void WebRequest::cancelAuth() +{ + ASSERT(m_loadState == Started, "cancelAuth called on a WebRequest not in STARTED state (state=%d)", m_loadState); + + m_request->CancelAuth(); +} + void WebRequest::startReading() { ASSERT(m_loadState == Response || m_loadState == GotData, "StartReading in state other than RESPONSE and GOTDATA"); diff --git a/WebKit/android/WebCoreSupport/WebRequest.h b/WebKit/android/WebCoreSupport/WebRequest.h index c5a101b..987d8ae 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.h +++ b/WebKit/android/WebCoreSupport/WebRequest.h @@ -69,6 +69,10 @@ public: virtual void OnReadCompleted(URLRequest*, int bytesRead); virtual void OnAuthRequired(URLRequest*, net::AuthChallengeInfo*); + // Methods called during a request by the UI code (via WebUrlLoaderClient). + void setAuth(const std::wstring& username, const std::wstring& password); + void cancelAuth(); + private: void startReading(); bool read(int* bytesRead); diff --git a/WebKit/android/WebCoreSupport/WebResponse.h b/WebKit/android/WebCoreSupport/WebResponse.h index 8fe65a8..fc90bf1 100644 --- a/WebKit/android/WebCoreSupport/WebResponse.h +++ b/WebKit/android/WebCoreSupport/WebResponse.h @@ -37,6 +37,8 @@ class ResourceResponse; class ResourceError; } +class URLRequest; + namespace android { class WebResponse { diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp index 6e1aa76..626b7f4 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp @@ -92,7 +92,8 @@ bool WebUrlLoaderClient::isActive() const } WebUrlLoaderClient::WebUrlLoaderClient(WebFrame* webFrame, WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest) - : m_resourceHandle(resourceHandle) + : m_webFrame(webFrame) + , m_resourceHandle(resourceHandle) , m_cancelling(false) , m_sync(false) , m_finished(false) @@ -189,6 +190,26 @@ void WebUrlLoaderClient::cancel() thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::cancel)); } +void WebUrlLoaderClient::setAuth(const std::string& username, const std::string& password) +{ + base::Thread* thread = ioThread(); + if (!thread) { + return; + } + std::wstring wUsername = base::SysUTF8ToWide(username); + std::wstring wPassword = base::SysUTF8ToWide(password); + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::setAuth, wUsername, wPassword)); +} + +void WebUrlLoaderClient::cancelAuth() +{ + base::Thread* thread = ioThread(); + if (!thread) { + return; + } + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::cancelAuth)); +} + void WebUrlLoaderClient::finish() { m_finished = true; @@ -200,7 +221,8 @@ void WebUrlLoaderClient::finish() } // This is called from the IO thread, and dispatches the callback to the main thread. -void WebUrlLoaderClient::maybeCallOnMainThread(CallbackFunction* function, void* context) { +void WebUrlLoaderClient::maybeCallOnMainThread(CallbackFunction* function, void* context) +{ if (m_sync) { AutoLock autoLock(*syncLock()); if (m_queue.empty()) { @@ -311,4 +333,26 @@ void WebUrlLoaderClient::didFinishLoading(void* data) loader->finish(); } +// static - on main thread +void WebUrlLoaderClient::authRequired(void* data) +{ + OwnPtr<LoaderData> loaderData(static_cast<LoaderData*>(data)); + WebUrlLoaderClient* loader = loaderData->loader; + + if (!loader->isActive()) { + return; + } + + std::string host = base::SysWideToUTF8(loaderData->authChallengeInfo->host_and_port); + std::string realm = base::SysWideToUTF8(loaderData->authChallengeInfo->realm); + + // TODO: Not clear whose responsibility it is to cache credentials. There's nothing + // in AuthChallengeInfo that seems suitable, so for safety we'll tell the UI *not* + // to use cached credentials. We may need to track this ourselves (pass "true" on + // the first call, then "false" for a second call if the credentials are rejected). + bool useCachedCredentials = false; + + loader->m_webFrame->didReceiveAuthenticationChallenge(loader, host, realm, useCachedCredentials); +} + } // namespace android diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h index 92c7bb5..23086cd 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h @@ -26,6 +26,8 @@ #ifndef WebUrlLoaderClient_h #define WebUrlLoaderClient_h +#if USE(CHROME_NETWORK_STACK) + #include "ChromiumIncludes.h" #include "RefCounted.h" #include "WebResponse.h" @@ -33,6 +35,8 @@ #include <string> #include <deque> +#include <string> +#include <vector> class Lock; class ConditionVariable; @@ -43,6 +47,7 @@ class Thread; namespace net { class IOBuffer; +class AuthChallengeInfo; } namespace android { @@ -67,6 +72,8 @@ public: void cancel(); void downloadFile(); void pauseLoad(bool pause) {} // Android method, does nothing for now + void setAuth(const std::string& username, const std::string& password); + void cancelAuth(); typedef void CallbackFunction(void*); @@ -82,12 +89,15 @@ public: static void didFinishLoading(void*); static void didFail(void*); static void willSendRequest(void*); + static void authRequired(void*); // Handle to the chrome IO thread static base::Thread* ioThread(); private: void finish(); + + WebFrame* m_webFrame; RefPtr<WebCore::ResourceHandle> m_resourceHandle; bool m_cancelling; bool m_sync; @@ -119,6 +129,7 @@ struct LoaderData { const int size; OwnPtr<std::string*> string; OwnPtr<std::vector<char> > vector; + scoped_refptr<net::AuthChallengeInfo> authChallengeInfo; LoaderData(WebUrlLoaderClient* l) : buffer(0), loader(l), size(0) { @@ -145,4 +156,6 @@ struct LoaderData { } // namespace android +#endif // USE(CHROME_NETWORK_STACK) + #endif diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index c1cb907..1d5eacb 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -83,6 +83,7 @@ #include "WebHistory.h" #include "WebIconDatabase.h" #include "WebFrameView.h" +#include "WebUrlLoaderClient.h" #include "WebViewCore.h" #include "android_graphics.h" #include "jni.h" @@ -209,6 +210,7 @@ struct WebFrame::JavaBrowserFrame jmethodID mDensity; jmethodID mGetFileSize; jmethodID mGetFile; + jmethodID mDidReceiveAuthenticationChallenge; AutoJObject frame(JNIEnv* env) { return getRealObject(env, mObj); } @@ -268,6 +270,8 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* mJavaFrame->mDensity = env->GetMethodID(clazz, "density","()F"); mJavaFrame->mGetFileSize = env->GetMethodID(clazz, "getFileSize", "(Ljava/lang/String;)I"); mJavaFrame->mGetFile = env->GetMethodID(clazz, "getFile", "(Ljava/lang/String;[BII)I"); + mJavaFrame->mDidReceiveAuthenticationChallenge = env->GetMethodID(clazz, "didReceiveAuthenticationChallenge", + "(ILjava/lang/String;Ljava/lang/String;Z)V"); LOG_ASSERT(mJavaFrame->mInputStreamForAndroidResource, "Could not find method inputStreamForAndroidResource"); LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource"); @@ -290,6 +294,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* LOG_ASSERT(mJavaFrame->mDensity, "Could not find method density"); LOG_ASSERT(mJavaFrame->mGetFileSize, "Could not find method getFileSize"); LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile"); + LOG_ASSERT(mJavaFrame->mDidReceiveAuthenticationChallenge, "Could not find method didReceiveAuthenticationChallenge"); mUserAgent = WTF::String(); mUserInitiatedAction = false; @@ -887,6 +892,24 @@ WebFrame::density() const return dpi; } +void +WebFrame::didReceiveAuthenticationChallenge(WebUrlLoaderClient* client, const std::string& host, const std::string& realm, bool useCachedCredentials) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); +#endif + JNIEnv* env = getJNIEnv(); + int jHandle = reinterpret_cast<int>(client); + jstring jHost = env->NewStringUTF(host.c_str()); + jstring jRealm = env->NewStringUTF(realm.c_str()); + + env->CallVoidMethod(mJavaFrame->frame(env).get(), + mJavaFrame->mDidReceiveAuthenticationChallenge, jHandle, jHost, jRealm, useCachedCredentials); + env->DeleteLocalRef(jHost); + env->DeleteLocalRef(jRealm); + checkException(env); +} + // ---------------------------------------------------------------------------- static void CallPolicyFunction(JNIEnv* env, jobject obj, jint func, jint decision) { @@ -1756,6 +1779,45 @@ static void OrientationChanged(JNIEnv *env, jobject obj, int orientation) pFrame->sendOrientationChangeEvent(orientation); } +static std::string jstringToStdString(JNIEnv* env, jstring jstr) { + jsize size = env->GetStringUTFLength(jstr); + jboolean isCopy; + const char* cstr = env->GetStringUTFChars(jstr, &isCopy); + std::string result(cstr, cstr + size); + env->ReleaseStringUTFChars(jstr, cstr); + return result; +} + +#if USE(CHROME_NETWORK_STACK) + +static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword) +{ + WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle); + std::string username = jstringToStdString(env, jUsername); + std::string password = jstringToStdString(env, jPassword); + client->setAuth(username, password); +} + +static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle) +{ + WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle); + client->cancelAuth(); +} + +#else + +static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword) +{ + LOGW("Chromium authentication API called, but libchromium is not available"); +} + +static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle) +{ + LOGW("Chromium authentication API called, but libchromium is not available"); +} + +#endif // USE(CHROME_NETWORK_STACK) + // ---------------------------------------------------------------------------- /* @@ -1811,7 +1873,11 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = { { "getFormTextData", "()Ljava/util/HashMap;", (void*) GetFormTextData }, { "nativeOrientationChanged", "(I)V", - (void*) OrientationChanged } + (void*) OrientationChanged }, + { "nativeAuthenticationProceed", "(ILjava/lang/String;Ljava/lang/String;)V", + (void*) AuthenticationProceed }, + { "nativeAuthenticationCancel", "(I)V", + (void*) AuthenticationCancel }, }; int register_webframe(JNIEnv* env) diff --git a/WebKit/android/jni/WebCoreFrameBridge.h b/WebKit/android/jni/WebCoreFrameBridge.h index 2b323e1..bcbbb47 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.h +++ b/WebKit/android/jni/WebCoreFrameBridge.h @@ -33,6 +33,7 @@ #include "PlatformString.h" #include "WebCoreRefObject.h" #include <jni.h> +#include <string> #include <wtf/RefCounted.h> namespace WebCore { @@ -48,6 +49,7 @@ namespace WebCore { namespace android { class WebViewCore; +class WebUrlLoaderClient; // one instance of WebFrame per Page for calling into Java's BrowserFrame class WebFrame : public WebCoreRefObject { @@ -109,6 +111,8 @@ class WebFrame : public WebCoreRefObject { float density() const; + void didReceiveAuthenticationChallenge(WebUrlLoaderClient*, const std::string& host, const std::string& realm, bool useCachedCredentials); + /** * When the user initiates an action (via trackball, key-press, or touch), * we set mUserInitiatedAction to true. If a load happens due to this click, |