0

[Android WebView] Support for fetching Android Java resources.

Add AwResource.java, a class that defines a set of resource IDs and
functionality to resolve those IDs to concrete resources.

Initially, we add three resources - two raw resources to represent
error pags and a string resource for default text encoding.

The embedder should set up the IDs before starting to use Chromium.

Review URL: https://codereview.chromium.org/11145026

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162205 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
benm@google.com
2012-10-16 19:15:48 +00:00
parent 4b80aecb29
commit dd81d183d4
13 changed files with 285 additions and 5 deletions

@ -27,6 +27,7 @@
'common/android_webview_message_generator.h',
'common/aw_content_client.cc',
'common/aw_content_client.h',
'common/aw_resource.h',
'common/render_view_messages.cc',
'common/render_view_messages.h',
'common/url_constants.cc',

@ -0,0 +1,22 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_COMMON_AW_RESOURCE_H_
#define ANDROID_WEBVIEW_COMMON_AW_RESOURCE_H_
#include <string>
// android_webview implements these with a JNI call to the
// AwResource Java class.
namespace android_webview {
namespace AwResource {
std::string GetLoadErrorPageContent();
std::string GetNoDomainPageContent();
std::string GetDefaultTextEncoding();
} // namespace AwResource
} // namsespace android_webview
#endif // ANDROID_WEBVIEW_COMMON_AW_RESOURCE_H_

@ -0,0 +1,118 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import android.content.res.Resources;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Scanner;
@JNINamespace("android_webview::AwResource")
public class AwResource {
// The following resource ID's must be initialized by the embedder.
// Raw resource ID for an HTML page to be displayed in the case of
// a specific load error.
public static int RAW_LOAD_ERROR;
// Raw resource ID for an HTML page to be displayed in the case of
// a generic load error. (It's called NO_DOMAIN for legacy reasons).
public static int RAW_NO_DOMAIN;
// String resource ID for the default text encoding to use.
public static int STRING_DEFAULT_TEXT_ENCODING;
// The embedder should inject a Resources object that will be used
// to resolve Resource IDs into the actual resources.
private static Resources sResources;
// Loading some resources is expensive, so cache the results.
private static Map<Integer, SoftReference<String> > sResourceCache;
private static final int TYPE_STRING = 0;
private static final int TYPE_RAW = 1;
public static void setResources(Resources resources) {
sResources = resources;
sResourceCache = new HashMap<Integer, SoftReference<String> >();
}
@CalledByNative
public static String getDefaultTextEncoding() {
return getResource(STRING_DEFAULT_TEXT_ENCODING, TYPE_STRING);
}
@CalledByNative
public static String getNoDomainPageContent() {
return getResource(RAW_NO_DOMAIN, TYPE_RAW);
}
@CalledByNative
public static String getLoadErrorPageContent() {
return getResource(RAW_LOAD_ERROR, TYPE_RAW);
}
private static String getResource(int resid, int type) {
assert resid != 0;
assert sResources != null;
assert sResourceCache != null;
String result = sResourceCache.get(resid) == null ?
null : sResourceCache.get(resid).get();
if (result == null) {
switch (type) {
case TYPE_STRING:
result = sResources.getString(resid);
break;
case TYPE_RAW:
result = getRawFileResourceContent(resid);
break;
default:
throw new IllegalArgumentException("Unknown resource type");
}
sResourceCache.put(resid, new SoftReference<String>(result));
}
return result;
}
private static String getRawFileResourceContent(int resid) {
assert resid != 0;
assert sResources != null;
InputStreamReader isr = null;
String result = null;
try {
isr = new InputStreamReader(
sResources.openRawResource(resid));
// \A tells the scanner to use the beginning of the input
// as the delimiter, hence causes it to read the entire text.
result = new Scanner(isr).useDelimiter("\\A").next();
} catch (Resources.NotFoundException e) {
return "";
} catch (NoSuchElementException e) {
return "";
}
finally {
try {
if (isr != null) {
isr.close();
}
} catch(IOException e) {
}
}
return result;
}
}

Binary file not shown.

After

(image error) Size: 13 KiB

@ -0,0 +1,5 @@
<html>
<head>
<title>This page intentionally left blank.</title>
</head>
</html>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<resources>
<string name="test_string">Hello, World!</string>
</resources>

@ -48,6 +48,7 @@ public class AndroidWebViewTestBase
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
AwTestResourceProvider.registerResources(context);
ContentViewCore.initChromiumBrowserProcess(
context, ContentView.MAX_RENDERERS_SINGLE_PROCESS);
}

@ -0,0 +1,35 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview.test;
import android.content.Context;
import org.chromium.android_webview.AwResource;
import org.chromium.content.app.AppResource;
public class AwTestResourceProvider {
private static boolean sInitialized;
static void registerResources(Context context) {
if (sInitialized) {
return;
}
AppResource.DRAWABLE_ICON_ACTION_BAR_SHARE = R.drawable.resource_icon;
AppResource.DRAWABLE_ICON_ACTION_BAR_WEB_SEARCH = R.drawable.resource_icon;
AppResource.STRING_ACTION_BAR_SHARE = R.string.test_string;
AppResource.STRING_ACTION_BAR_WEB_SEARCH = R.string.test_string;
AwResource.setResources(context.getResources());
AwResource.RAW_LOAD_ERROR = R.raw.blank_html;
AwResource.RAW_NO_DOMAIN = R.raw.blank_html;
AwResource.STRING_DEFAULT_TEXT_ENCODING = R.string.test_string;
sInitialized = true;
}
}

@ -10,6 +10,7 @@
#include "android_webview/native/aw_contents.h"
#include "android_webview/native/aw_contents_io_thread_client_impl.h"
#include "android_webview/native/aw_http_auth_handler.h"
#include "android_webview/native/aw_resource.h"
#include "android_webview/native/cookie_manager.h"
#include "android_webview/native/intercepted_request_data_impl.h"
#include "android_webview/native/js_result_handler.h"
@ -33,6 +34,7 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = {
{ "AwContents", RegisterAwContents },
{ "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl},
{ "AwHttpAuthHandler", RegisterAwHttpAuthHandler },
{ "AwResource", AwResource::RegisterAwResource },
{ "CookieManager", RegisterCookieManager },
{ "InterceptedRequestDataImpl", RegisterInterceptedRequestData },
{ "JsResultHandler", RegisterJsResultHandler },

@ -0,0 +1,45 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/native/aw_resource.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "jni/AwResource_jni.h"
namespace android_webview {
namespace AwResource {
// These JNI functions are used by the Renderer but rely on Java data
// structures that exist in the Browser. By virtue of the WebView running
// in single process we can just reach over and use them. When WebView is
// multi-process capable, we'll need to rethink these. See crbug.com/156062.
std::string GetLoadErrorPageContent() {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> content =
Java_AwResource_getLoadErrorPageContent(env);
return base::android::ConvertJavaStringToUTF8(content);
}
std::string GetNoDomainPageContent() {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> content =
Java_AwResource_getNoDomainPageContent(env);
return base::android::ConvertJavaStringToUTF8(content);
}
std::string GetDefaultTextEncoding() {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> encoding =
Java_AwResource_getDefaultTextEncoding(env);
return base::android::ConvertJavaStringToUTF8(encoding);
}
bool RegisterAwResource(JNIEnv* env) {
return RegisterNativesImpl(env) >= 0;
}
} // namespace AwResource
} // namespace android_webview

@ -0,0 +1,20 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_NATIVE_AW_RESOURCE_H_
#define ANDROID_WEBVIEW_NATIVE_AW_RESOURCE_H_
#include "base/android/jni_android.h"
#include <string>
namespace android_webview {
namespace AwResource {
bool RegisterAwResource(JNIEnv* env);
} // namespace AwResource
} // namsespace android_webview
#endif // ANDROID_WEBVIEW_NATIVE_AW_RESOURCE_H_

@ -39,6 +39,8 @@
'aw_http_auth_handler.h',
'aw_javascript_dialog_creator.cc',
'aw_javascript_dialog_creator.h',
'aw_resource.h',
'aw_resource.cc',
'aw_web_contents_delegate.cc',
'aw_web_contents_delegate.h',
'cookie_manager.cc',
@ -68,6 +70,7 @@
'../java/src/org/chromium/android_webview/AwContents.java',
'../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java',
'../java/src/org/chromium/android_webview/AwHttpAuthHandler.java',
'../java/src/org/chromium/android_webview/AwResource.java',
'../java/src/org/chromium/android_webview/CookieManager.java',
'../java/src/org/chromium/android_webview/InterceptedRequestData.java',
'../java/src/org/chromium/android_webview/JsResultHandler.java',

@ -4,11 +4,16 @@
#include "android_webview/renderer/aw_content_renderer_client.h"
#include "android_webview/common/aw_resource.h"
#include "android_webview/common/url_constants.h"
#include "android_webview/renderer/aw_render_view_ext.h"
#include "base/utf_string_conversions.h"
#include "content/public/renderer/render_thread.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
namespace android_webview {
@ -35,8 +40,7 @@ void AwContentRendererClient::RenderViewCreated(
}
std::string AwContentRendererClient::GetDefaultEncoding() {
// TODO(boliu): query android system locale.
return std::string("ISO-8859-1");
return AwResource::GetDefaultTextEncoding();
}
WebKit::WebPlugin* AwContentRendererClient::CreatePluginReplacement(
@ -49,8 +53,7 @@ WebKit::WebPlugin* AwContentRendererClient::CreatePluginReplacement(
bool AwContentRendererClient::HasErrorPage(int http_status_code,
std::string* error_domain) {
// TODO(boliu): Implement our own error pages.
return false;
return http_status_code >= 400;
}
void AwContentRendererClient::GetNavigationErrorStrings(
@ -58,7 +61,21 @@ void AwContentRendererClient::GetNavigationErrorStrings(
const WebKit::WebURLError& error,
std::string* error_html,
string16* error_description) {
// TODO(boliu): Implement our own error pages.
if (error_html) {
GURL error_url(failed_request.url());
std::string err = UTF16ToUTF8(error.localizedDescription);
std::string contents;
if (err.empty()) {
contents = AwResource::GetNoDomainPageContent();
} else {
contents = AwResource::GetLoadErrorPageContent();
ReplaceSubstringsAfterOffset(&contents, 0, "%e", err);
}
ReplaceSubstringsAfterOffset(&contents, 0, "%s",
error_url.possibly_invalid_spec());
*error_html = contents;
}
}
unsigned long long AwContentRendererClient::VisitedLinkHash(