summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/java_library_common.mk1
-rw-r--r--android_webview/libwebviewchromium.gypi1
-rw-r--r--content/app/BUILD.gn1
-rw-r--r--content/app/android/library_loader_hooks.cc4
-rw-r--r--content/browser/BUILD.gn1
-rw-r--r--content/browser/renderer_host/compositor_impl_android.cc7
-rw-r--r--content/browser/renderer_host/compositor_impl_android.h3
-rw-r--r--content/content_app.gypi1
-rw-r--r--content/content_browser.gypi1
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/public/browser/android/compositor.h7
-rw-r--r--content/public/test/content_test_suite_base.cc2
-rw-r--r--content/test/BUILD.gn5
-rw-r--r--ui/android/BUILD.gn32
-rw-r--r--ui/android/DEPS10
-rw-r--r--ui/android/OWNERS4
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/LayoutResource.java57
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/Resource.java38
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/ResourceLoader.java71
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/ResourceManager.java169
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/async/AsyncPreloadResourceLoader.java116
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/dynamics/BitmapDynamicResource.java66
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResource.java24
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResourceLoader.java69
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/dynamics/ViewResourceAdapter.java164
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/statics/NinePatchData.java136
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/statics/StaticResource.java132
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/statics/StaticResourceLoader.java32
-rw-r--r--ui/android/java/src/org/chromium/ui/resources/system/SystemResourceLoader.java93
-rw-r--r--ui/android/resources/resource_manager.cc138
-rw-r--r--ui/android/resources/resource_manager.h91
-rw-r--r--ui/android/resources/ui_resource_android.cc50
-rw-r--r--ui/android/resources/ui_resource_android.h49
-rw-r--r--ui/android/ui_android.gyp45
-rw-r--r--ui/android/ui_android_export.h31
-rw-r--r--ui/android/ui_android_jni_registrar.cc22
-rw-r--r--ui/android/ui_android_jni_registrar.h19
37 files changed, 1691 insertions, 2 deletions
diff --git a/android_webview/java_library_common.mk b/android_webview/java_library_common.mk
index 56f36ac..15126cf 100644
--- a/android_webview/java_library_common.mk
+++ b/android_webview/java_library_common.mk
@@ -44,6 +44,7 @@ LOCAL_SRC_FILES += \
# Java files generated from .template rules. This list should match list of java dependencies in
# android_webview/libwebviewchromium.gyp
LOCAL_GENERATED_SOURCES := \
+$(call intermediates-dir-for,GYP,shared)/enums/android_resource_type_java/org/chromium/ui/resources/AndroidResourceType.java \
$(call intermediates-dir-for,GYP,shared)/enums/bitmap_format_java/org/chromium/ui/gfx/BitmapFormat.java \
$(call intermediates-dir-for,GYP,shared)/enums/cert_verify_status_android_java/org/chromium/net/CertVerifyStatusAndroid.java \
$(call intermediates-dir-for,GYP,shared)/enums/certificate_mime_types_java/org/chromium/net/CertificateMimeType.java \
diff --git a/android_webview/libwebviewchromium.gypi b/android_webview/libwebviewchromium.gypi
index 099ca4b..8b2d40c 100644
--- a/android_webview/libwebviewchromium.gypi
+++ b/android_webview/libwebviewchromium.gypi
@@ -30,6 +30,7 @@
'../net/net.gyp:network_change_notifier_types_java',
'../net/net.gyp:net_errors_java',
'../net/net.gyp:private_key_types_java',
+ '../ui/android/ui_android.gyp:android_resource_type_java',
'../ui/android/ui_android.gyp:bitmap_format_java',
'../ui/android/ui_android.gyp:page_transition_types_java',
'../ui/android/ui_android.gyp:system_ui_resource_type_java',
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn
index 82af6d7..d5a9371 100644
--- a/content/app/BUILD.gn
+++ b/content/app/BUILD.gn
@@ -44,6 +44,7 @@ if (is_win) {
"//content/public/android:jni",
"//skia",
"//third_party/android_tools:cpu_features",
+ "//ui/android",
]
}
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc
index d09e21e..d044e6b 100644
--- a/content/app/android/library_loader_hooks.cc
+++ b/content/app/android/library_loader_hooks.cc
@@ -25,6 +25,7 @@
#include "device/battery/android/battery_jni_registrar.h"
#include "media/base/android/media_jni_registrar.h"
#include "net/android/net_jni_registrar.h"
+#include "ui/android/ui_android_jni_registrar.h"
#include "ui/base/android/ui_base_jni_registrar.h"
#include "ui/gfx/android/gfx_jni_registrar.h"
#include "ui/gl/android/gl_jni_registrar.h"
@@ -69,6 +70,9 @@ bool EnsureJniRegistered(JNIEnv* env) {
if (!media::RegisterJni(env))
return false;
+ if (!ui::RegisterUIAndroidJni(env))
+ return false;
+
g_jni_init_done = true;
}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 3a98908..930a3e2 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -329,6 +329,7 @@ source_set("browser") {
"//content/public/android:jni",
"//media",
"//mojo/android:libsystem_java",
+ "//ui/android",
]
libs += [ "jnigraphics" ]
}
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index c070ac5..6da1273 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -165,8 +165,9 @@ bool CompositorImpl::IsInitialized() {
CompositorImpl::CompositorImpl(CompositorClient* client,
gfx::NativeWindow root_window)
: root_layer_(cc::Layer::Create()),
+ resource_manager_(&ui_resource_provider_),
surface_id_allocator_(
- new cc::SurfaceIdAllocator(++g_surface_id_namespace)),
+ new cc::SurfaceIdAllocator(++g_surface_id_namespace)),
has_transparent_background_(false),
device_scale_factor_(1),
window_(NULL),
@@ -322,6 +323,10 @@ UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
return ui_resource_provider_;
}
+ui::ResourceManager& CompositorImpl::GetResourceManager() {
+ return resource_manager_;
+}
+
ui::SystemUIResourceManager& CompositorImpl::GetSystemUIResourceManager() {
return ui_resource_provider_.GetSystemUIResourceManager();
}
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 0d83445..67f5d5d 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -18,6 +18,7 @@
#include "content/public/browser/android/compositor.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "third_party/khronos/GLES2/gl2.h"
+#include "ui/android/resources/resource_manager.h"
#include "ui/base/android/system_ui_resource_manager.h"
#include "ui/base/android/window_android_compositor.h"
@@ -61,6 +62,7 @@ class CONTENT_EXPORT CompositorImpl
virtual void SetHasTransparentBackground(bool flag) override;
virtual void SetNeedsComposite() override;
virtual UIResourceProvider& GetUIResourceProvider() override;
+ virtual ui::ResourceManager& GetResourceManager() override;
// LayerTreeHostClient implementation.
virtual void WillBeginMainFrame(int frame_id) override {}
@@ -139,6 +141,7 @@ class CONTENT_EXPORT CompositorImpl
scoped_ptr<cc::LayerTreeHost> host_;
content::UIResourceProviderImpl ui_resource_provider_;
+ ui::ResourceManager resource_manager_;
scoped_ptr<OnscreenDisplayClient> display_client_;
scoped_ptr<cc::SurfaceIdAllocator> surface_id_allocator_;
diff --git a/content/content_app.gypi b/content/content_app.gypi
index c8ad3f0..d0a3296 100644
--- a/content/content_app.gypi
+++ b/content/content_app.gypi
@@ -46,6 +46,7 @@
'dependencies': [
'content.gyp:content_jni_headers',
'../skia/skia.gyp:skia',
+ '../ui/android/ui_android.gyp:ui_android',
],
'includes': [
'../build/android/cpufeatures.gypi',
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index cf826c6..ea18825 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1810,6 +1810,7 @@
'dependencies': [
'../media/media.gyp:media',
'../mojo/mojo_base.gyp:libmojo_system_java',
+ '../ui/android/ui_android.gyp:ui_android',
'content.gyp:content_jni_headers',
],
'defines': ['APPCACHE_USE_SIMPLE_CACHE'],
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 0224b40..7f28b16 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -355,6 +355,7 @@
}],
['OS=="android"', {
'dependencies': [
+ '../ui/android/ui_android.gyp:ui_android',
'../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'content.gyp:content_v8_external_data',
],
diff --git a/content/public/browser/android/compositor.h b/content/public/browser/android/compositor.h
index 25a61c8..e7dd30e 100644
--- a/content/public/browser/android/compositor.h
+++ b/content/public/browser/android/compositor.h
@@ -23,6 +23,10 @@ namespace gfx {
class JavaBitmap;
}
+namespace ui {
+class ResourceManager;
+}
+
namespace content {
class CompositorClient;
class UIResourceProvider;
@@ -68,6 +72,9 @@ class CONTENT_EXPORT Compositor {
// Returns the UI resource provider associated with the compositor.
virtual UIResourceProvider& GetUIResourceProvider() = 0;
+ // Returns the resource manager associated with the compositor.
+ virtual ui::ResourceManager& GetResourceManager() = 0;
+
protected:
Compositor() {}
};
diff --git a/content/public/test/content_test_suite_base.cc b/content/public/test/content_test_suite_base.cc
index afaeea7..81821b0 100644
--- a/content/public/test/content_test_suite_base.cc
+++ b/content/public/test/content_test_suite_base.cc
@@ -32,6 +32,7 @@
#include "content/public/browser/android/compositor.h"
#include "media/base/android/media_jni_registrar.h"
#include "net/android/net_jni_registrar.h"
+#include "ui/android/ui_android_jni_registrar.h"
#include "ui/base/android/ui_base_jni_registrar.h"
#include "ui/gfx/android/gfx_jni_registrar.h"
#include "ui/gl/android/gl_jni_registrar.h"
@@ -84,6 +85,7 @@ void ContentTestSuiteBase::Initialize() {
media::RegisterJni(env);
net::android::RegisterJni(env);
ui::android::RegisterJni(env);
+ ui::RegisterUIAndroidJni(env);
ui::gl::android::RegisterJni(env);
ui::shell_dialogs::RegisterJni(env);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index eae2cd8..1aca2e2 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -127,7 +127,10 @@ static_library("test_support") {
}
if (is_android) {
- deps += [ "//ui/shell_dialogs" ]
+ deps += [
+ "//ui/android",
+ "//ui/shell_dialogs"
+ ]
}
if (is_win) {
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 1d4b2e1..8ee9722 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -2,6 +2,36 @@ import("//build/config/android/rules.gni")
assert(is_android)
+component("android") {
+ output_name = "ui_android"
+ sources = [
+ "resources/resource_manager.cc",
+ "resources/resource_manager.h",
+ "resources/ui_resource_android.cc",
+ "resources/ui_resource_android.h",
+ "ui_android_export.h",
+ "ui_android_jni_registrar.cc",
+ "ui_android_jni_registrar.h",
+ ]
+
+ defines = [ "UI_ANDROID_IMPLEMENTATION" ]
+
+ deps = [
+ "//cc",
+ "//skia",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ ":ui_android_jni_headers",
+ ]
+}
+
+generate_jni("ui_android_jni_headers") {
+ sources = [
+ "java/src/org/chromium/ui/resources/ResourceManager.java",
+ ]
+ jni_package = "ui_android"
+}
+
java_cpp_enum("java_enums_srcjar") {
sources = [
"../base/page_transition_types.h",
@@ -9,6 +39,7 @@ java_cpp_enum("java_enums_srcjar") {
"../base/android/system_ui_resource_type.h",
"../base/ime/text_input_type.h",
"../gfx/android/java_bitmap.h",
+ "resources/resource_manager.h",
]
outputs = [
"org/chromium/ui/WindowOpenDisposition.java",
@@ -16,6 +47,7 @@ java_cpp_enum("java_enums_srcjar") {
"org/chromium/ui/base/SystemUIResourceType.java",
"org/chromium/ui/base/ime/TextInputType.java",
"org/chromium/ui/gfx/BitmapFormat.java",
+ "org/chromium/ui/resources/AndroidResourceType.java",
]
}
diff --git a/ui/android/DEPS b/ui/android/DEPS
new file mode 100644
index 0000000..c9ee84c
--- /dev/null
+++ b/ui/android/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+ "+cc/resources/ui_resource_client.h",
+ "+cc/resources/ui_resource_bitmap.h",
+ "+content/public/browser/android/ui_resource_client_android.h",
+ "+content/public/browser/android/ui_resource_provider.h",
+ "+jni",
+ "+skia/ext",
+ "+third_party/skia",
+ "+ui/gfx",
+]
diff --git a/ui/android/OWNERS b/ui/android/OWNERS
index 85d8f5a..1fd40a0 100644
--- a/ui/android/OWNERS
+++ b/ui/android/OWNERS
@@ -2,3 +2,7 @@ jdduke@chromium.org
miguelg@chromium.org
newt@chromium.org
tedchoc@chromium.org
+
+# for UI resources
+dtrainor@chromium.org
+jaekyun@chromium.org
diff --git a/ui/android/java/src/org/chromium/ui/resources/LayoutResource.java b/ui/android/java/src/org/chromium/ui/resources/LayoutResource.java
new file mode 100644
index 0000000..47e3f1f
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/LayoutResource.java
@@ -0,0 +1,57 @@
+// Copyright 2014 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.ui.resources;
+
+import android.graphics.Rect;
+import android.graphics.RectF;
+
+/**
+ * A resource that provides sizing information for layouts.
+ */
+public class LayoutResource {
+ private final RectF mPadding;
+ private final RectF mBitmapSize;
+ private final RectF mAperture;
+
+ public LayoutResource(float pxToDp, Resource resource) {
+ Rect padding = resource.getPadding();
+ Rect bitmapSize = resource.getBitmapSize();
+ Rect aperture = resource.getAperture();
+
+ mPadding = new RectF(padding.left * pxToDp, padding.top * pxToDp, padding.right * pxToDp,
+ padding.bottom * pxToDp);
+
+ mBitmapSize = new RectF(bitmapSize.left * pxToDp, bitmapSize.top * pxToDp,
+ bitmapSize.right * pxToDp, bitmapSize.bottom * pxToDp);
+
+ mAperture = new RectF(aperture.left * pxToDp, aperture.top * pxToDp,
+ aperture.right * pxToDp, aperture.bottom * pxToDp);
+ }
+
+ /**
+ * @return The padded content area of this resource in dp. For 9-patches this will represent
+ * the valid content of the 9-patch. It can mean other things for other Resources
+ * though.
+ */
+ public RectF getPadding() {
+ return mPadding;
+ }
+
+ /**
+ * @return The size of the bitmap in dp;
+ */
+ public RectF getBitmapSize() {
+ return mBitmapSize;
+ }
+
+ /**
+ * @return The aperture of this resource in dp. For 9-patches this will represent the area of
+ * the {@link Bitmap} that should not be stretched. It can mean other things for other
+ * Resources though.
+ */
+ public RectF getAperture() {
+ return mAperture;
+ }
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/Resource.java b/ui/android/java/src/org/chromium/ui/resources/Resource.java
new file mode 100644
index 0000000..5884a88
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/Resource.java
@@ -0,0 +1,38 @@
+// Copyright 2014 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.ui.resources;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+
+/**
+ * A basic resource interface that all assets must use to be exposed to the CC layer as
+ * UIResourceIds.
+ */
+public interface Resource {
+ /**
+ * This may be called more than once so if possible avoid doing redundant work.
+ * @return A {@link Bitmap} representing the resource.
+ */
+ Bitmap getBitmap();
+
+ /**
+ * @return The size of the bitmap.
+ */
+ Rect getBitmapSize();
+
+ /**
+ * @return The padded content area of this resource. For 9-patches this will represent the
+ * valid content of the 9-patch. It can mean other things for other Resources though.
+ */
+ Rect getPadding();
+
+ /**
+ * @return The aperture of this resource. For 9-patches this will represent the area of the
+ * {@link Bitmap} that should not be stretched. It can mean other things for other
+ * Resources though.
+ */
+ Rect getAperture();
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/ResourceLoader.java b/ui/android/java/src/org/chromium/ui/resources/ResourceLoader.java
new file mode 100644
index 0000000..eef765e
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/ResourceLoader.java
@@ -0,0 +1,71 @@
+// Copyright 2014 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.ui.resources;
+
+/**
+ * A class responsible for loading {@link Resource}s for the {@link ResourceManager}.
+ */
+public abstract class ResourceLoader {
+ /**
+ * A callback that specifies when a {@link Resource} has been loaded and can be exposed to the
+ * CC layer.
+ */
+ public interface ResourceLoaderCallback {
+ /**
+ * Called when a resource as finished loading. Note that it is up to the caller to recycle
+ * any {@link android.graphics.Bitmap}s or clean up any state after making this call.
+ * @param resType The {@link ResourceType} that loaded the resource.
+ * @param resId The Android id of the loaded resource.
+ * @param resource The {@link Resource} of the resource, or {@code null} if one could
+ * not be loaded.
+ */
+ void onResourceLoaded(int resType, int resId, Resource resource);
+ }
+
+ private final int mResourceType;
+ private final ResourceLoaderCallback mCallback;
+
+ /**
+ * Creates an instance of a {@link ResourceLoader}.
+ * @param resourceType The resource type category this {@link ResourceLoader} is loading.
+ * @param callback The {@link ResourceLoaderCallback} to notify when a {@link Resource} is
+ * loaded.
+ */
+ public ResourceLoader(int resourceType, ResourceLoaderCallback callback) {
+ mResourceType = resourceType;
+ mCallback = callback;
+ }
+
+ /**
+ * @return What resource type this {@link ResourceLoader} is responsible for loading.
+ */
+ public int getResourceType() {
+ return mResourceType;
+ }
+
+ /**
+ * Requests that a resource specified by {@code resId} be loaded from this
+ * {@link ResourceLoader}. This may or may not actually load the resource and notify the
+ * {@link ResourceLoaderCallback} depending on the internal behavior of the particular loader.
+ * @param resId The id of the {@link Resource} to load.
+ */
+ public abstract void loadResource(int resId);
+
+ /**
+ * Requests that a resource be pre-loaded. This will typically happen asynchronously.
+ * @param resId The id of the {@link Resource} to load.
+ */
+ public abstract void preloadResource(int resId);
+
+ /**
+ * A helper method for subclasses to notify that the {@link Resource} specified by {@code resId}
+ * is done loading.
+ * @param resId The id of the {@link Resource} that loaded or failed.
+ * @param resource The {@link Resource}, or {@code null} if the load failed.
+ */
+ protected void notifyLoadFinished(int resId, Resource resource) {
+ if (mCallback != null) mCallback.onResourceLoaded(getResourceType(), resId, resource);
+ }
+}
diff --git a/ui/android/java/src/org/chromium/ui/resources/ResourceManager.java b/ui/android/java/src/org/chromium/ui/resources/ResourceManager.java
new file mode 100644
index 0000000..d6574fe
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/ResourceManager.java
@@ -0,0 +1,169 @@
+// Copyright 2014 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.ui.resources;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.util.SparseArray;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.ui.resources.ResourceLoader.ResourceLoaderCallback;
+import org.chromium.ui.resources.dynamics.DynamicResource;
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
+import org.chromium.ui.resources.statics.StaticResourceLoader;
+import org.chromium.ui.resources.system.SystemResourceLoader;
+
+/**
+ * The Java component of a manager for all static resources to be loaded and used by CC layers.
+ * This class does not hold any resource state, but passes it directly to native as they are loaded.
+ */
+@JNINamespace("ui")
+public class ResourceManager implements ResourceLoaderCallback {
+ private final SparseArray<ResourceLoader> mResourceLoaders = new SparseArray<ResourceLoader>();
+ private final SparseArray<SparseArray<LayoutResource>> mLoadedResources =
+ new SparseArray<SparseArray<LayoutResource>>();
+
+ private final float mPxToDp;
+
+ private long mNativeResourceManagerPtr;
+
+ private ResourceManager(Context context, long staticResourceManagerPtr) {
+ Resources resources = context.getResources();
+ mPxToDp = 1.f / resources.getDisplayMetrics().density;
+
+ // Register ResourceLoaders
+ registerResourceLoader(new StaticResourceLoader(
+ AndroidResourceType.STATIC, this, resources));
+ registerResourceLoader(new DynamicResourceLoader(
+ AndroidResourceType.DYNAMIC, this));
+ registerResourceLoader(new DynamicResourceLoader(
+ AndroidResourceType.DYNAMIC_BITMAP, this));
+ registerResourceLoader(new SystemResourceLoader(
+ AndroidResourceType.SYSTEM, this, context));
+
+ mNativeResourceManagerPtr = staticResourceManagerPtr;
+ }
+
+ /**
+ * Creates an instance of a {@link ResourceManager}. This will
+ * @param context A {@link Context} instance to grab {@link Resources} from.
+ * @param staticResourceManagerPtr A pointer to the native component of this class.
+ * @return A new instance of a {@link ResourceManager}.
+ */
+ @CalledByNative
+ private static ResourceManager create(Context context, long staticResourceManagerPtr) {
+ return new ResourceManager(context, staticResourceManagerPtr);
+ }
+
+ /**
+ * @return A reference to the {@link DynamicResourceLoader} that provides
+ * {@link DynamicResource} objects to this class.
+ */
+ public DynamicResourceLoader getDynamicResourceLoader() {
+ return (DynamicResourceLoader) mResourceLoaders.get(
+ AndroidResourceType.DYNAMIC);
+ }
+
+ /**
+ * @return A reference to the {@link DynamicResourceLoader} for bitmaps that provides
+ * {@link BitmapDynamicResource} objects to this class.
+ */
+ public DynamicResourceLoader getBitmapDynamicResourceLoader() {
+ return (DynamicResourceLoader) mResourceLoaders.get(
+ AndroidResourceType.DYNAMIC_BITMAP);
+ }
+
+ /**
+ * Automatically loads any synchronous resources specified in |syncIds| and will start
+ * asynchronous reads for any asynchronous resources specified in |asyncIds|.
+ * @param type AndroidResourceType which will be loaded.
+ * @param syncIds Resource ids which will be loaded synchronously.
+ * @param asyncIds Resource ids which will be loaded asynchronously.
+ */
+ public void preloadResources(int type, int[] syncIds, int[] asyncIds) {
+ ResourceLoader loader = mResourceLoaders.get(type);
+ if (asyncIds != null) {
+ for (Integer resId : asyncIds) {
+ loader.preloadResource(resId);
+ }
+ }
+
+ if (syncIds != null) {
+ for (Integer resId : syncIds) {
+ loader.loadResource(resId);
+ }
+ }
+ }
+
+ /**
+ * @param resType The type of the Android resource.
+ * @param resId The id of the Android resource.
+ * @return The corresponding {@link LayoutResource}.
+ */
+ public LayoutResource getResource(int resType, int resId) {
+ SparseArray<LayoutResource> bucket = mLoadedResources.get(resType);
+ return bucket != null ? bucket.get(resId) : null;
+ }
+
+ @Override
+ public void onResourceLoaded(int resType, int resId, Resource resource) {
+ if (resource == null) return;
+
+ saveMetadataForLoadedResource(resType, resId, resource);
+
+ if (mNativeResourceManagerPtr == 0) return;
+ Rect padding = resource.getPadding();
+ Rect aperture = resource.getAperture();
+
+ nativeOnResourceReady(mNativeResourceManagerPtr, resType, resId, resource.getBitmap(),
+ padding.left, padding.top, padding.right, padding.bottom,
+ aperture.left, aperture.top, aperture.right, aperture.bottom);
+ }
+
+ private void saveMetadataForLoadedResource(int resType, int resId, Resource resource) {
+ SparseArray<LayoutResource> bucket = mLoadedResources.get(resType);
+ if (bucket == null) {
+ bucket = new SparseArray<LayoutResource>();
+ mLoadedResources.put(resType, bucket);
+ }
+ bucket.put(resId, new LayoutResource(mPxToDp, resource));
+ }
+
+ @CalledByNative
+ private void destroy() {
+ assert mNativeResourceManagerPtr != 0;
+ mNativeResourceManagerPtr = 0;
+ }
+
+ @CalledByNative
+ private void resourceRequested(int resType, int resId) {
+ ResourceLoader loader = mResourceLoaders.get(resType);
+ if (loader != null) loader.loadResource(resId);
+ }
+
+ @CalledByNative
+ private void preloadResource(int resType, int resId) {
+ ResourceLoader loader = mResourceLoaders.get(resType);
+ if (loader != null) loader.preloadResource(resId);
+ }
+
+ @CalledByNative
+ private long getNativePtr() {
+ return mNativeResourceManagerPtr;
+ }
+
+ private void registerResourceLoader(ResourceLoader loader) {
+ mResourceLoaders.put(loader.getResourceType(), loader);
+ }
+
+ private native void nativeOnResourceReady(long nativeResourceManager, int resType,
+ int resId, Bitmap bitmap, int paddingLeft, int paddingTop, int paddingRight,
+ int paddingBottom, int apertureLeft, int apertureTop, int apertureRight,
+ int apertureBottom);
+
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/async/AsyncPreloadResourceLoader.java b/ui/android/java/src/org/chromium/ui/resources/async/AsyncPreloadResourceLoader.java
new file mode 100644
index 0000000..fb27244
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/async/AsyncPreloadResourceLoader.java
@@ -0,0 +1,116 @@
+// Copyright 2014 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.ui.resources.async;
+
+import android.os.AsyncTask;
+import android.util.SparseArray;
+
+import org.chromium.ui.resources.Resource;
+import org.chromium.ui.resources.ResourceLoader;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Handles loading Android resources from disk asynchronously and synchronously.
+ */
+public class AsyncPreloadResourceLoader extends ResourceLoader {
+ /**
+ * Responsible for actually creating a {@link Resource} from a specific resource id.
+ */
+ public interface ResourceCreator {
+ /**
+ * Creates a {@link Resource} from {@code resId}. Note that this method may be called from
+ * a background thread. No assumptions can be made on which thread this will be called
+ * from!
+ * @param resId The id of the resource to load.
+ * @return A {@link Resource} instance that represents {@code resId} or {@code null} if
+ * none can be loaded.
+ */
+ Resource create(int resId);
+ }
+
+ private final SparseArray<AsyncLoadTask> mOutstandingLoads = new SparseArray<AsyncLoadTask>();
+ private final ResourceCreator mCreator;
+
+ /**
+ * Creates a {@link AsyncPreloadResourceLoader}.
+ * @param resourceType The resource type this loader is responsible for loading.
+ * @param callback The {@link ResourceLoaderCallback} to notify when a {@link Resource} is
+ * done loading.
+ * @param creator A {@link ResourceCreator} instance that will be used to create the
+ * {@link Resource}s.
+ */
+ public AsyncPreloadResourceLoader(int resourceType, ResourceLoaderCallback callback,
+ ResourceCreator creator) {
+ super(resourceType, callback);
+ mCreator = creator;
+ }
+
+ /**
+ * Loads a resource synchronously. This will still call the {@link ResourceLoaderCallback} on
+ * completion. If the resource is currently being loaded asynchronously this will wait for that
+ * task to complete before returning. If the resource is queued to be read asynchronously later
+ * this will cancel that request.
+ * @param resId The Android resource id to load.
+ */
+ @Override
+ public void loadResource(int resId) {
+ AsyncLoadTask task = mOutstandingLoads.get(resId);
+
+ if (task != null) {
+ if (!task.cancel(false)) {
+ try {
+ registerResource(task.get(), resId);
+ } catch (InterruptedException e) {
+ notifyLoadFinished(resId, null);
+ } catch (ExecutionException e) {
+ notifyLoadFinished(resId, null);
+ }
+ return;
+ }
+ }
+ registerResource(mCreator.create(resId), resId);
+ }
+
+ /**
+ * Loads a resource asynchronously. The load will be queued if other resources are currently
+ * being loaded. The {@link ResourceLoaderCallback} will be notified on completion.
+ * @param resId The Android resource id to load.
+ */
+ @Override
+ public void preloadResource(int resId) {
+ if (mOutstandingLoads.get(resId) != null) return;
+ AsyncLoadTask task = new AsyncLoadTask(resId);
+ task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ mOutstandingLoads.put(resId, task);
+ }
+
+ private void registerResource(Resource resource, int resourceId) {
+ notifyLoadFinished(resourceId, resource);
+ if (resource != null) resource.getBitmap().recycle();
+ mOutstandingLoads.remove(resourceId);
+ }
+
+ private class AsyncLoadTask extends AsyncTask<Void, Void, Resource> {
+ private final int mResourceId;
+
+ public AsyncLoadTask(int resourceId) {
+ mResourceId = resourceId;
+ }
+
+ @Override
+ protected Resource doInBackground(Void... params) {
+ return mCreator.create(mResourceId);
+ }
+
+ @Override
+ protected void onPostExecute(Resource resource) {
+ // If we've been removed from the list of outstanding load tasks, don't broadcast the
+ // callback.
+ if (mOutstandingLoads.get(mResourceId) == null) return;
+ registerResource(resource, mResourceId);
+ }
+ }
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/dynamics/BitmapDynamicResource.java b/ui/android/java/src/org/chromium/ui/resources/dynamics/BitmapDynamicResource.java
new file mode 100644
index 0000000..4d5b501
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/dynamics/BitmapDynamicResource.java
@@ -0,0 +1,66 @@
+// Copyright 2014 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.ui.resources.dynamics;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+
+/**
+ * A basic implementation of {@link DynamicResource} to handle updatable bitmaps.
+ */
+public class BitmapDynamicResource implements DynamicResource {
+ private static final Rect EMPTY_RECT = new Rect();
+
+ private final int mResId;
+ private Bitmap mBitmap;
+ private final Rect mSize = new Rect();
+ private boolean mIsDirty = true;
+
+ public BitmapDynamicResource(int resourceId) {
+ mResId = resourceId;
+ }
+
+ /**
+ * @return A unique id for this resource.
+ */
+ public int getResId() {
+ return mResId;
+ }
+
+ /**
+ * @param bitmap A bitmap to update this resource.
+ */
+ public void setBitmap(Bitmap bitmap) {
+ mIsDirty = true;
+ mBitmap = bitmap;
+ mSize.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ }
+
+ @Override
+ public Bitmap getBitmap() {
+ mIsDirty = false;
+ return mBitmap;
+ }
+
+ @Override
+ public Rect getBitmapSize() {
+ return mSize;
+ }
+
+ @Override
+ public Rect getPadding() {
+ return EMPTY_RECT;
+ }
+
+ @Override
+ public Rect getAperture() {
+ return EMPTY_RECT;
+ }
+
+ @Override
+ public boolean isDirty() {
+ return mIsDirty;
+ }
+}
diff --git a/ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResource.java b/ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResource.java
new file mode 100644
index 0000000..c31e25b
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResource.java
@@ -0,0 +1,24 @@
+// Copyright 2014 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.ui.resources.dynamics;
+
+import org.chromium.ui.resources.Resource;
+
+/**
+ * A representation of a dynamic resource. The contents of the resource might change from frame to
+ * frame.
+ */
+public interface DynamicResource extends Resource {
+ /**
+ * Note that this is called for every access to the resource during a frame. If a resource is
+ * dirty, it should not be dirty again during the same looper call.
+ *
+ * TODO(dtrainor): Add checks so that a dynamic resource **can't** be built more than once each
+ * frame.
+ *
+ * @return Whether or not this resource is dirty and the CC component should be rebuilt.
+ */
+ boolean isDirty();
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResourceLoader.java b/ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResourceLoader.java
new file mode 100644
index 0000000..6145cae
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/dynamics/DynamicResourceLoader.java
@@ -0,0 +1,69 @@
+// Copyright 2014 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.ui.resources.dynamics;
+
+import android.util.SparseArray;
+
+import org.chromium.ui.resources.ResourceLoader;
+
+/**
+ * Handles managing dynamic resources. This is basically a list of dynamic resources that checks
+ * {@link DynamicResource#isDirty()} before notifying the {@link ResourceLoaderCallback}.
+ */
+public class DynamicResourceLoader extends ResourceLoader {
+ private final SparseArray<DynamicResource> mDynamicResources =
+ new SparseArray<DynamicResource>();
+
+ /**
+ * Builds a {@link DynamicResourceLoader} instance.
+ * @param resourceType The resource type this loader is responsible for loading.
+ * @param callback A {@link ResourceLoaderCallback} to be notified when the dynamic resource
+ * has changed. The callback will only be notified if
+ * {@link #loadResource(int)} is called.
+ */
+ public DynamicResourceLoader(int resourceType, ResourceLoaderCallback callback) {
+ super(resourceType, callback);
+ }
+
+ /**
+ * Registers a {@link DynamicResource} to be tracked and exposed by this class.
+ * @param resId The Android id to use. This should be an actual Android id (R.id.some_id).
+ * @param resource The {@link DynamicResource} to track and expose.
+ */
+ public void registerResource(int resId, DynamicResource resource) {
+ assert mDynamicResources.get(resId) == null;
+ mDynamicResources.put(resId, resource);
+ }
+
+ /**
+ * Unregisters a {@link DynamicResource} specified by {@code resId}.
+ * @param resId The Android id representing the {@link DynamicResource}.
+ */
+ public void unregisterResource(int resId) {
+ mDynamicResources.remove(resId);
+ }
+
+ /**
+ * Called when a {@link DynamicResource} was requested. This will notify the
+ * {@link ResourceLoaderCallback} if the resource has new contents.
+ * @param resId The Android id representing the {@link DynamicResource}.
+ */
+ @Override
+ public void loadResource(int resId) {
+ DynamicResource resource = mDynamicResources.get(resId);
+ if (resource == null) return;
+
+ if (resource.isDirty()) notifyLoadFinished(resId, resource);
+ }
+
+ /**
+ * Since this class relies solely on registration it does not support preloading resources.
+ */
+ @Override
+ public void preloadResource(int resId) {
+ // Not implemented.
+ assert false : "Preloading dynamic resources isn't supported.";
+ }
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/dynamics/ViewResourceAdapter.java b/ui/android/java/src/org/chromium/ui/resources/dynamics/ViewResourceAdapter.java
new file mode 100644
index 0000000..13b8179
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/dynamics/ViewResourceAdapter.java
@@ -0,0 +1,164 @@
+// Copyright 2014 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.ui.resources.dynamics;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+
+import org.chromium.base.TraceEvent;
+
+/**
+ * An adapter that exposes a {@link View} as a {@link DynamicResource}. In order to properly use
+ * this adapter {@link ViewResourceAdapter#invalidate(Rect)} must be called when parts of the
+ * {@link View} are invalidated. For {@link ViewGroup}s the easiest way to do this is to override
+ * {@link View#invalidateChildInParent(int[], Rect)}.
+ */
+public class ViewResourceAdapter implements DynamicResource, OnLayoutChangeListener {
+ private final View mView;
+ private final Rect mDirtyRect = new Rect();
+ private final Rect mContentPadding = new Rect();
+ private final Rect mContentAperture = new Rect();
+
+ private Bitmap mBitmap;
+ private Rect mBitmapSize = new Rect();
+
+ /**
+ * Builds a {@link ViewResourceAdapter} instance around {@code view}.
+ * @param view The {@link View} to expose as a {@link Resource}.
+ */
+ public ViewResourceAdapter(View view) {
+ mView = view;
+ mView.addOnLayoutChangeListener(this);
+ }
+
+ /**
+ * If this resource is not dirty ({@link #isDirty()} returned {@code false}), this will return
+ * the last {@link Bitmap} built from the {@link View}. Otherwise it will recapture a
+ * {@link Bitmap} of the {@link View}.
+ * @see {@link DynamicResource#getBitmap()}.
+ * @return A {@link Bitmap} representing the {@link View}.
+ */
+ @Override
+ public Bitmap getBitmap() {
+ if (!isDirty()) return mBitmap;
+ TraceEvent.begin("ViewResourceAdapter:getBitmap");
+ validateBitmap();
+
+ Canvas canvas = new Canvas(mBitmap);
+
+ onCaptureStart(canvas, mDirtyRect.isEmpty() ? null : mDirtyRect);
+
+ if (!mDirtyRect.isEmpty()) canvas.clipRect(mDirtyRect);
+ mView.draw(canvas);
+
+ onCaptureEnd();
+
+ mDirtyRect.setEmpty();
+ TraceEvent.end("ViewResourceAdapter:getBitmap");
+ return mBitmap;
+ }
+
+ @Override
+ public Rect getBitmapSize() {
+ return mBitmapSize;
+ }
+
+ @Override
+ public Rect getPadding() {
+ computeContentPadding(mContentPadding);
+
+ return mContentPadding;
+ }
+
+ @Override
+ public Rect getAperture() {
+ computeContentAperture(mContentAperture);
+
+ return mContentAperture;
+ }
+
+ @Override
+ public boolean isDirty() {
+ if (mBitmap == null) mDirtyRect.set(0, 0, mView.getWidth(), mView.getHeight());
+
+ return !mDirtyRect.isEmpty();
+ }
+
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ final int width = right - left;
+ final int height = bottom - top;
+ final int oldWidth = oldRight - oldLeft;
+ final int oldHeight = oldBottom - oldTop;
+
+ if (width != oldWidth || height != oldHeight) mDirtyRect.set(0, 0, width, height);
+ }
+
+ /**
+ * Invalidates a particular region of the {@link View} that needs to be repainted.
+ * @param dirtyRect The region to invalidate, or {@code null} if the entire {@code Bitmap}
+ * should be redrawn.
+ */
+ public void invalidate(Rect dirtyRect) {
+ if (dirtyRect == null) {
+ mDirtyRect.set(0, 0, mView.getWidth(), mView.getHeight());
+ } else {
+ mDirtyRect.union(dirtyRect);
+ }
+ }
+
+ /**
+ * Called before {@link View#draw(Canvas)} is called.
+ * @param canvas The {@link Canvas} that will be drawn to.
+ * @param dirtyRect The dirty {@link Rect} or {@code null} if the entire area is being redrawn.
+ */
+ protected void onCaptureStart(Canvas canvas, Rect dirtyRect) {
+ }
+
+ /**
+ * Called after {@link View#draw(Canvas)}.
+ */
+ protected void onCaptureEnd() {
+ }
+
+ /**
+ * Gives overriding classes the chance to specify a different content padding.
+ * @param outContentPadding The resulting content padding.
+ */
+ protected void computeContentPadding(Rect outContentPadding) {
+ outContentPadding.set(0, 0, mView.getWidth(), mView.getHeight());
+ }
+
+ /**
+ * Gives overriding classes the chance to specify a different content aperture.
+ * @param outContentAperture The resulting content aperture.
+ */
+ protected void computeContentAperture(Rect outContentAperture) {
+ outContentAperture.set(0, 0, mView.getWidth(), mView.getHeight());
+ }
+
+ private void validateBitmap() {
+ if (mBitmap != null
+ && (mBitmap.getWidth() != mView.getWidth()
+ || mBitmap.getHeight() != mView.getHeight())) {
+ mBitmap.recycle();
+ mBitmap = null;
+ }
+
+ if (mView.getWidth() == 0 || mView.getHeight() == 0) return;
+
+ if (mBitmap == null) {
+ mBitmap = Bitmap.createBitmap(
+ mView.getWidth(), mView.getHeight(), Bitmap.Config.ARGB_8888);
+ mBitmap.setHasAlpha(true);
+ mDirtyRect.set(0, 0, mView.getWidth(), mView.getHeight());
+ mBitmapSize.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ }
+ }
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/statics/NinePatchData.java b/ui/android/java/src/org/chromium/ui/resources/statics/NinePatchData.java
new file mode 100644
index 0000000..2c04bec
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/statics/NinePatchData.java
@@ -0,0 +1,136 @@
+// Copyright 2014 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.ui.resources.statics;
+
+import android.graphics.Bitmap;
+import android.graphics.NinePatch;
+import android.graphics.Rect;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * A helper class to decode and expose relevant 9-patch data from a Bitmap.
+ */
+class NinePatchData {
+ private final int mWidth;
+ private final int mHeight;
+ private final Rect mPadding;
+ private final int[] mDivX;
+ private final int[] mDivY;
+
+ private Rect mAperture;
+
+ /**
+ * Creates a {@link NinePatchData} that stores 9-patch metadata.
+ * @param width The width of the underlying bitmap.
+ * @param height The height of the underlying bitmap.
+ * @param padding The padding of the 9-patch for the content area. This padding is a set of
+ * insets (left = left padding, top = top padding, right = right padding,
+ * bottom = bottom padding).
+ * @param divX A run-length encoded list of stretch regions along the x dimension. The
+ * regions will go from 0 -> divX[0] - 1, divX[0] -> divX[1] - 1, etc..
+ * @param divY A run-length encoded list of stretch regions along the y dimension. The
+ * regions will go from 0 -> divY[0] - 1, divY[0] -> divY[1] - 1, etc..
+ */
+ private NinePatchData(int width, int height, Rect padding, int[] divX, int[] divY) {
+ mWidth = width;
+ mHeight = height;
+ mPadding = new Rect(
+ padding.left, padding.top, mWidth - padding.right, mHeight - padding.bottom);
+
+ mDivX = new int[divX.length];
+ mDivY = new int[divY.length];
+
+ System.arraycopy(divX, 0, mDivX, 0, divX.length);
+ System.arraycopy(divY, 0, mDivY, 0, divY.length);
+
+ mAperture = new Rect(mDivX[0], mDivY[0], mDivX[1], mDivY[1]);
+ }
+
+ /**
+ * @return The padded content area of this 9-patch.
+ */
+ public Rect getPadding() {
+ return mPadding;
+ }
+
+ /**
+ * This class only exposes one 9-patch stretch region.
+ * @return The aperture of this 9-patch. This specifies the center of the 9-patch, with the
+ * surrounding areas being stretchable.
+ */
+ public Rect getAperture() {
+ return mAperture;
+ }
+
+ /**
+ * Attempts to decode 9-patch data from a {@link Bitmap}.
+ * @param bitmap The {@link Bitmap} to check.
+ * @return An instance of {@link NinePatchData} representing the 9-patch information
+ * encoded in {@code bitmap} or {@code null} if the {@link Bitmap} wasn't a
+ * 9-patch.
+ */
+ public static NinePatchData create(Bitmap bitmap) {
+ if (bitmap == null) return null;
+
+ try {
+ byte[] chunk = bitmap.getNinePatchChunk();
+ if (chunk == null || !NinePatch.isNinePatchChunk(chunk)) return null;
+
+ ByteBuffer buffer = ByteBuffer.wrap(chunk).order(ByteOrder.nativeOrder());
+
+ // int8_t wasDeserialized
+ if (buffer.get() == 0) return null;
+
+ // int8_t numXDivs
+ int numDivX = buffer.get();
+ if (numDivX == 0 || (numDivX & 0x01) != 0) return null;
+
+ // int8_t numYDivs
+ int numDivY = buffer.get();
+ if (numDivY == 0 || (numDivY & 0x01) != 0) return null;
+
+ // int8_t numColors
+ buffer.get();
+
+ // uint32_t xDivsOffset
+ buffer.getInt();
+
+ // uint32_t yDivsOffset
+ buffer.getInt();
+
+ Rect padding = new Rect();
+
+ // uint32_t paddingLeft
+ padding.left = buffer.getInt();
+
+ // uint32_t paddingRight
+ padding.right = buffer.getInt();
+
+ // uint32_t paddingTop
+ padding.top = buffer.getInt();
+
+ // uint32_t paddingBottom
+ padding.bottom = buffer.getInt();
+
+ // uint32_t colorsOffset
+ buffer.getInt();
+
+ // uint32_t uint32_t uint32_t ...
+ int[] divX = new int[numDivX];
+ for (int i = 0; i < numDivX; i++) divX[i] = buffer.getInt();
+
+ // uint32_t uint32_t uint32_t ...
+ int[] divY = new int[numDivY];
+ for (int i = 0; i < numDivY; i++) divY[i] = buffer.getInt();
+
+ return new NinePatchData(bitmap.getWidth(), bitmap.getHeight(), padding, divX, divY);
+ } catch (BufferUnderflowException ex) {
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/statics/StaticResource.java b/ui/android/java/src/org/chromium/ui/resources/statics/StaticResource.java
new file mode 100644
index 0000000..26a9155
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/statics/StaticResource.java
@@ -0,0 +1,132 @@
+// Copyright 2014 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.ui.resources.statics;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+import org.chromium.ui.resources.Resource;
+
+/**
+ * A representation of a static resource and all related information for drawing it. In general
+ * this means a {@link Bitmap} and a potential {@link NinePatchData}.
+ */
+public class StaticResource implements Resource {
+ private final Bitmap mBitmap;
+ private final NinePatchData mNinePatchData;
+ private final Rect mBitmapSize;
+
+ /**
+ * Creates a {@link StaticResource} that represents {@code bitmap}. This will automatically
+ * pull out the {@link NinePatchData} from {@code bitmap} if it exists.
+ * @param bitmap The {@link Bitmap} to build a {@link StaticResource} of.
+ */
+ public StaticResource(Bitmap bitmap) {
+ mBitmap = bitmap;
+ mNinePatchData = NinePatchData.create(mBitmap);
+ mBitmapSize = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ }
+
+ @Override
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ @Override
+ public Rect getBitmapSize() {
+ return mBitmapSize;
+ }
+
+ @Override
+ public Rect getPadding() {
+ return mNinePatchData != null ? mNinePatchData.getPadding() : mBitmapSize;
+ }
+
+ @Override
+ public Rect getAperture() {
+ return mNinePatchData != null ? mNinePatchData.getAperture() : mBitmapSize;
+ }
+
+ /**
+ * Attempts to load the Android resource specified by {@code resId} from {@code resources}.
+ * This will attempt to first load the resource as a {@code Bitmap}. If that fails it will try
+ * to load the resource as a {@link Drawable}.
+ * @param resources The {@link Resources} instance to load from.
+ * @param resId The id of the Android resource to load.
+ * @param fitWidth The smallest width the image can be. The image will be shrunk to scale to
+ * try to get close to this value. Or use {@code 0} to use the intrinsic
+ * size.
+ * @param fitHeight The smallest height the image can be. The image will be shrunk to scale to
+ * try to get close to this value. Or use {@code 0} to use the intrinsic
+ * size.
+ * @return The loaded {@link StaticResource} or {@code null} if the resource could not
+ * be loaded.
+ */
+ public static StaticResource create(Resources resources, int resId, int fitWidth,
+ int fitHeight) {
+ if (resId <= 0) return null;
+ Bitmap bitmap = decodeBitmap(resources, resId, fitWidth, fitHeight);
+ if (bitmap == null) bitmap = decodeDrawable(resources, resId, fitWidth, fitHeight);
+ if (bitmap == null) return null;
+
+ return new StaticResource(bitmap);
+ }
+
+ private static Bitmap decodeBitmap(Resources resources, int resId, int fitWidth,
+ int fitHeight) {
+ BitmapFactory.Options options = createOptions(resources, resId, fitWidth, fitHeight);
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ Bitmap bitmap = BitmapFactory.decodeResource(resources, resId, options);
+
+ if (bitmap == null) return null;
+ if (bitmap.getConfig() == options.inPreferredConfig) return bitmap;
+
+ Bitmap convertedBitmap = Bitmap.createBitmap(
+ bitmap.getWidth(), bitmap.getHeight(), options.inPreferredConfig);
+ Canvas canvas = new Canvas(convertedBitmap);
+ canvas.drawBitmap(bitmap, 0, 0, null);
+ bitmap.recycle();
+ return convertedBitmap;
+ }
+
+ private static Bitmap decodeDrawable(Resources resources, int resId, int fitWidth,
+ int fitHeight) {
+ try {
+ Drawable drawable = resources.getDrawable(resId);
+ int width = Math.max(drawable.getMinimumWidth(), Math.max(fitWidth, 1));
+ int height = Math.max(drawable.getMinimumHeight(), Math.max(fitHeight, 1));
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, width, height);
+ drawable.draw(canvas);
+ return bitmap;
+ } catch (Resources.NotFoundException ex) {
+ return null;
+ }
+ }
+
+ private static BitmapFactory.Options createOptions(Resources resources, int resId,
+ int fitWidth, int fitHeight) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ if (fitWidth == 0 || fitHeight == 0) return options;
+
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeResource(resources, resId, options);
+ options.inJustDecodeBounds = false;
+
+ if (options.outHeight <= fitHeight && options.outWidth <= fitWidth) return options;
+
+ int heightRatio = Math.round((float) options.outHeight / (float) fitHeight);
+ int widthRatio = Math.round((float) options.outWidth / (float) fitWidth);
+ options.inSampleSize = Math.min(heightRatio, widthRatio);
+
+ return options;
+ }
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/statics/StaticResourceLoader.java b/ui/android/java/src/org/chromium/ui/resources/statics/StaticResourceLoader.java
new file mode 100644
index 0000000..3444188
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/statics/StaticResourceLoader.java
@@ -0,0 +1,32 @@
+// Copyright 2014 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.ui.resources.statics;
+
+import android.content.res.Resources;
+
+import org.chromium.ui.resources.Resource;
+import org.chromium.ui.resources.async.AsyncPreloadResourceLoader;
+
+/**
+ * Handles loading Android resources from disk asynchronously and synchronously.
+ */
+public class StaticResourceLoader extends AsyncPreloadResourceLoader {
+ /**
+ * Creates a {@link StaticResourceLoader}.
+ * @param resourceType The resource type this loader is responsible for loading.
+ * @param callback The {@link ResourceLoaderCallback} to notify when a {@link Resource} is
+ * done loading.
+ * @param resources The {@link Resources} instance to load Android resources from.
+ */
+ public StaticResourceLoader(int resourceType, ResourceLoaderCallback callback,
+ final Resources resources) {
+ super(resourceType, callback, new ResourceCreator() {
+ @Override
+ public Resource create(int resId) {
+ return StaticResource.create(resources, resId, 0, 0);
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/resources/system/SystemResourceLoader.java b/ui/android/java/src/org/chromium/ui/resources/system/SystemResourceLoader.java
new file mode 100644
index 0000000..cae57f6
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/system/SystemResourceLoader.java
@@ -0,0 +1,93 @@
+// Copyright 2014 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.ui.resources.system;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.RectF;
+
+import org.chromium.ui.base.SystemUIResourceType;
+import org.chromium.ui.gfx.DeviceDisplayInfo;
+import org.chromium.ui.resources.Resource;
+import org.chromium.ui.resources.async.AsyncPreloadResourceLoader;
+import org.chromium.ui.resources.statics.StaticResource;
+
+/**
+ * Handles loading system specific resources like overscroll and edge glows.
+ */
+public class SystemResourceLoader extends AsyncPreloadResourceLoader {
+ private static final float SIN_PI_OVER_6 = 0.5f;
+ private static final float COS_PI_OVER_6 = 0.866f;
+
+ /**
+ * Creates an instance of a {@link SystemResourceLoader}.
+ * @param resourceType The resource type this loader is responsible for loading.
+ * @param callback The {@link ResourceLoaderCallback} to notify when a {@link Resource} is
+ * done loading.
+ * @param resources A {@link Resources} instance to load assets from.
+ */
+ public SystemResourceLoader(int resourceType, ResourceLoaderCallback callback,
+ final Context context) {
+ super(resourceType, callback, new ResourceCreator() {
+ @Override
+ public Resource create(int resId) {
+ return createResource(context, resId);
+ }
+ });
+ }
+
+ private static Resource createResource(Context context, int resId) {
+ switch (resId) {
+ case SystemUIResourceType.OVERSCROLL_EDGE:
+ return StaticResource.create(Resources.getSystem(),
+ getResourceId("android:drawable/overscroll_edge"), 128, 12);
+ case SystemUIResourceType.OVERSCROLL_GLOW:
+ return StaticResource.create(Resources.getSystem(),
+ getResourceId("android:drawable/overscroll_glow"), 128, 64);
+ case SystemUIResourceType.OVERSCROLL_GLOW_L:
+ return createOverscrollGlowLBitmap(context);
+ }
+ return null;
+ }
+
+ private static Resource createOverscrollGlowLBitmap(Context context) {
+ DeviceDisplayInfo displayInfo = DeviceDisplayInfo.create(context);
+ int screenWidth = displayInfo.getPhysicalDisplayWidth() != 0
+ ? displayInfo.getPhysicalDisplayWidth() : displayInfo.getDisplayWidth();
+ int screenHeight = displayInfo.getPhysicalDisplayHeight() != 0
+ ? displayInfo.getPhysicalDisplayHeight() : displayInfo.getDisplayHeight();
+
+ float arcWidth = Math.min(screenWidth, screenHeight) * 0.5f / SIN_PI_OVER_6;
+ float y = COS_PI_OVER_6 * arcWidth;
+ float height = arcWidth - y;
+
+ float arcRectX = -arcWidth / 2.f;
+ float arcRectY = -arcWidth - y;
+ float arcRectWidth = arcWidth * 2.f;
+ float arcRectHeight = arcWidth * 2.f;
+ RectF arcRect = new RectF(
+ arcRectX, arcRectY, arcRectX + arcRectWidth, arcRectY + arcRectHeight);
+
+ Paint arcPaint = new Paint();
+ arcPaint.setAntiAlias(true);
+ arcPaint.setAlpha(0xBB);
+ arcPaint.setStyle(Style.FILL);
+
+ Bitmap bitmap = Bitmap.createBitmap((int) arcWidth, (int) height, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawArc(arcRect, 45, 90, true, arcPaint);
+
+ return new StaticResource(bitmap);
+ }
+
+ private static int getResourceId(String name) {
+ Resources systemResources = Resources.getSystem();
+ return systemResources.getIdentifier(name, null, null);
+ }
+} \ No newline at end of file
diff --git a/ui/android/resources/resource_manager.cc b/ui/android/resources/resource_manager.cc
new file mode 100644
index 0000000..557661f
--- /dev/null
+++ b/ui/android/resources/resource_manager.cc
@@ -0,0 +1,138 @@
+// Copyright 2014 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 "ui/android/resources/resource_manager.h"
+
+#include "content/public/browser/android/ui_resource_provider.h"
+#include "jni/ResourceManager_jni.h"
+#include "ui/android/resources/ui_resource_android.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/geometry/insets_f.h"
+
+namespace ui {
+
+ResourceManager::Resource::Resource() {
+}
+
+ResourceManager::Resource::~Resource() {
+}
+
+gfx::Rect ResourceManager::Resource::Border(const gfx::Size& bounds) {
+ return Border(bounds, gfx::InsetsF(1.f, 1.f, 1.f, 1.f));
+}
+
+gfx::Rect ResourceManager::Resource::Border(const gfx::Size& bounds,
+ const gfx::InsetsF& scale) {
+ // Calculate whether or not we need to scale down the border if the bounds of
+ // the layer are going to be smaller than the aperture padding.
+ float x_scale = std::min((float)bounds.width() / size.width(), 1.f);
+ float y_scale = std::min((float)bounds.height() / size.height(), 1.f);
+
+ float left_scale = std::min(x_scale * scale.left(), 1.f);
+ float right_scale = std::min(x_scale * scale.right(), 1.f);
+ float top_scale = std::min(y_scale * scale.top(), 1.f);
+ float bottom_scale = std::min(y_scale * scale.bottom(), 1.f);
+
+ return gfx::Rect(aperture.x() * left_scale, aperture.y() * top_scale,
+ (size.width() - aperture.width()) * right_scale,
+ (size.height() - aperture.height()) * bottom_scale);
+}
+
+// static
+ResourceManager* ResourceManager::FromJavaObject(jobject jobj) {
+ return reinterpret_cast<ResourceManager*>(Java_ResourceManager_getNativePtr(
+ base::android::AttachCurrentThread(), jobj));
+}
+
+ResourceManager::ResourceManager(
+ content::UIResourceProvider* ui_resource_provider)
+ : ui_resource_provider_(ui_resource_provider) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ java_obj_.Reset(env, Java_ResourceManager_create(
+ env, base::android::GetApplicationContext(),
+ reinterpret_cast<intptr_t>(this)).obj());
+ DCHECK(!java_obj_.is_null());
+}
+
+ResourceManager::~ResourceManager() {
+ Java_ResourceManager_destroy(base::android::AttachCurrentThread(),
+ java_obj_.obj());
+}
+
+base::android::ScopedJavaLocalRef<jobject> ResourceManager::GetJavaObject(
+ JNIEnv* env) {
+ return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
+}
+
+ResourceManager::Resource* ResourceManager::GetResource(
+ AndroidResourceType res_type,
+ int res_id) {
+ DCHECK_GE(res_type, ANDROID_RESOURCE_TYPE_FIRST);
+ DCHECK_LE(res_type, ANDROID_RESOURCE_TYPE_LAST);
+
+ Resource* resource = resources_[res_type].Lookup(res_id);
+
+ if (!resource || res_type == ANDROID_RESOURCE_TYPE_DYNAMIC ||
+ res_type == ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP) {
+ Java_ResourceManager_resourceRequested(base::android::AttachCurrentThread(),
+ java_obj_.obj(), res_type, res_id);
+ resource = resources_[res_type].Lookup(res_id);
+ }
+
+ return resource;
+}
+
+void ResourceManager::PreloadResource(AndroidResourceType res_type,
+ int res_id) {
+ DCHECK_GE(res_type, ANDROID_RESOURCE_TYPE_FIRST);
+ DCHECK_LE(res_type, ANDROID_RESOURCE_TYPE_LAST);
+
+ // Don't send out a query if the resource is already loaded.
+ if (resources_[res_type].Lookup(res_id))
+ return;
+
+ Java_ResourceManager_preloadResource(base::android::AttachCurrentThread(),
+ java_obj_.obj(), res_type, res_id);
+}
+
+void ResourceManager::OnResourceReady(JNIEnv* env,
+ jobject jobj,
+ jint res_type,
+ jint res_id,
+ jobject bitmap,
+ jint padding_left,
+ jint padding_top,
+ jint padding_right,
+ jint padding_bottom,
+ jint aperture_left,
+ jint aperture_top,
+ jint aperture_right,
+ jint aperture_bottom) {
+ DCHECK_GE(res_type, ANDROID_RESOURCE_TYPE_FIRST);
+ DCHECK_LE(res_type, ANDROID_RESOURCE_TYPE_LAST);
+
+ Resource* resource = resources_[res_type].Lookup(res_id);
+ if (!resource) {
+ resource = new Resource();
+ resources_[res_type].AddWithID(resource, res_id);
+ }
+
+ gfx::JavaBitmap jbitmap(bitmap);
+ resource->size = jbitmap.size();
+ resource->padding.SetRect(padding_left, padding_top,
+ padding_right - padding_left,
+ padding_bottom - padding_top);
+ resource->aperture.SetRect(aperture_left, aperture_top,
+ aperture_right - aperture_left,
+ aperture_bottom - aperture_top);
+ resource->ui_resource =
+ UIResourceAndroid::CreateFromJavaBitmap(ui_resource_provider_, jbitmap);
+}
+
+// static
+bool ResourceManager::RegisterResourceManager(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace ui
diff --git a/ui/android/resources/resource_manager.h b/ui/android/resources/resource_manager.h
new file mode 100644
index 0000000..730d4dc
--- /dev/null
+++ b/ui/android/resources/resource_manager.h
@@ -0,0 +1,91 @@
+// Copyright 2014 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 UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_
+#define UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_
+
+#include "base/android/jni_android.h"
+#include "base/id_map.h"
+#include "cc/resources/ui_resource_client.h"
+#include "ui/android/ui_android_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace content {
+class UIResourceProvider;
+}
+
+namespace ui {
+
+class UIResourceAndroid;
+
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.ui.resources
+enum AndroidResourceType {
+ ANDROID_RESOURCE_TYPE_STATIC = 0,
+ ANDROID_RESOURCE_TYPE_DYNAMIC,
+ ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP,
+ ANDROID_RESOURCE_TYPE_SYSTEM,
+
+ ANDROID_RESOURCE_TYPE_COUNT,
+ ANDROID_RESOURCE_TYPE_FIRST = ANDROID_RESOURCE_TYPE_STATIC,
+ ANDROID_RESOURCE_TYPE_LAST = ANDROID_RESOURCE_TYPE_SYSTEM,
+};
+
+class UI_ANDROID_EXPORT ResourceManager {
+ public:
+ struct Resource {
+ public:
+ Resource();
+ ~Resource();
+ gfx::Rect Border(const gfx::Size& bounds);
+ gfx::Rect Border(const gfx::Size& bounds, const gfx::InsetsF& scale);
+
+ scoped_ptr<UIResourceAndroid> ui_resource;
+ gfx::Size size;
+ gfx::Rect padding;
+ gfx::Rect aperture;
+ };
+
+ static ResourceManager* FromJavaObject(jobject jobj);
+
+ explicit ResourceManager(content::UIResourceProvider* ui_resource_provider);
+ virtual ~ResourceManager();
+
+ base::android::ScopedJavaLocalRef<jobject> GetJavaObject(JNIEnv* env);
+
+ ResourceManager::Resource* GetResource(AndroidResourceType res_type,
+ int res_id);
+ void PreloadResource(AndroidResourceType res_type, int res_id);
+
+ // Called from Java ----------------------------------------------------------
+ void OnResourceReady(JNIEnv* env,
+ jobject jobj,
+ jint res_type,
+ jint res_id,
+ jobject bitmap,
+ jint padding_left,
+ jint padding_top,
+ jint padding_right,
+ jint padding_bottom,
+ jint aperture_left,
+ jint aperture_top,
+ jint aperture_right,
+ jint aperture_bottom);
+
+ static bool RegisterResourceManager(JNIEnv* env);
+
+ private:
+ typedef IDMap<Resource, IDMapOwnPointer> ResourceMap;
+
+ content::UIResourceProvider* ui_resource_provider_;
+ ResourceMap resources_[ANDROID_RESOURCE_TYPE_COUNT];
+
+ base::android::ScopedJavaGlobalRef<jobject> java_obj_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceManager);
+};
+
+} // namespace ui
+
+#endif // UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_
diff --git a/ui/android/resources/ui_resource_android.cc b/ui/android/resources/ui_resource_android.cc
new file mode 100644
index 0000000..c242630
--- /dev/null
+++ b/ui/android/resources/ui_resource_android.cc
@@ -0,0 +1,50 @@
+// Copyright 2014 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 "ui/android/resources/ui_resource_android.h"
+
+#include "base/logging.h"
+#include "content/public/browser/android/ui_resource_provider.h"
+
+namespace ui {
+
+scoped_ptr<UIResourceAndroid> UIResourceAndroid::CreateFromJavaBitmap(
+ content::UIResourceProvider* provider,
+ const gfx::JavaBitmap& java_bitmap) {
+ SkBitmap skbitmap = gfx::CreateSkBitmapFromJavaBitmap(java_bitmap);
+ skbitmap.setImmutable();
+
+ return make_scoped_ptr(new UIResourceAndroid(provider, skbitmap));
+}
+
+UIResourceAndroid::~UIResourceAndroid() {
+ if (id_ && provider_)
+ provider_->DeleteUIResource(id_);
+}
+
+cc::UIResourceBitmap UIResourceAndroid::GetBitmap(cc::UIResourceId uid,
+ bool resource_lost) {
+ DCHECK(!bitmap_.empty());
+ return cc::UIResourceBitmap(bitmap_);
+}
+
+cc::UIResourceId UIResourceAndroid::id() {
+ if (id_)
+ return id_;
+ if (!provider_ || bitmap_.empty())
+ return 0;
+ id_ = provider_->CreateUIResource(this);
+ return id_;
+}
+
+void UIResourceAndroid::UIResourceIsInvalid() {
+ id_ = 0;
+}
+
+UIResourceAndroid::UIResourceAndroid(content::UIResourceProvider* provider,
+ const SkBitmap& skbitmap)
+ : provider_(provider), bitmap_(skbitmap), id_(0) {
+}
+
+} // namespace ui
diff --git a/ui/android/resources/ui_resource_android.h b/ui/android/resources/ui_resource_android.h
new file mode 100644
index 0000000..c18c0d7
--- /dev/null
+++ b/ui/android/resources/ui_resource_android.h
@@ -0,0 +1,49 @@
+// Copyright 2014 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 UI_ANDROID_RESOURCES_UI_RESOURCE_ANDROID_H_
+#define UI_ANDROID_RESOURCES_UI_RESOURCE_ANDROID_H_
+
+#include "base/basictypes.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "content/public/browser/android/ui_resource_client_android.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/android/resources/ui_resource_android.h"
+#include "ui/android/ui_android_export.h"
+#include "ui/gfx/android/java_bitmap.h"
+
+namespace ui {
+
+class UI_ANDROID_EXPORT UIResourceAndroid
+ : public content::UIResourceClientAndroid {
+ public:
+ static scoped_ptr<UIResourceAndroid> CreateFromJavaBitmap(
+ content::UIResourceProvider* provider,
+ const gfx::JavaBitmap& java_bitmap);
+
+ ~UIResourceAndroid() override;
+
+ // cc::UIResourceClient implementation.
+ cc::UIResourceBitmap GetBitmap(cc::UIResourceId uid,
+ bool resource_lost) override;
+
+ // UIResourceClientAndroid implementation.
+ void UIResourceIsInvalid() override;
+
+ cc::UIResourceId id();
+
+ private:
+ UIResourceAndroid(content::UIResourceProvider* provider,
+ const SkBitmap& skbitmap);
+
+ content::UIResourceProvider* provider_;
+ SkBitmap bitmap_;
+ cc::UIResourceId id_;
+
+ DISALLOW_COPY_AND_ASSIGN(UIResourceAndroid);
+};
+
+} // namespace ui
+
+#endif // UI_ANDROID_RESOURCES_UI_RESOURCE_ANDROID_H_
diff --git a/ui/android/ui_android.gyp b/ui/android/ui_android.gyp
index f4e6ce6..1acc7f4 100644
--- a/ui/android/ui_android.gyp
+++ b/ui/android/ui_android.gyp
@@ -8,6 +8,50 @@
},
'targets': [
{
+ # GN version: //ui/android
+ 'target_name': 'ui_android',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../cc/cc.gyp:cc',
+ '../../base/base.gyp:base',
+ '../../skia/skia.gyp:skia',
+ '../gfx/gfx.gyp:gfx',
+ '../gfx/gfx.gyp:gfx_geometry',
+ 'ui_android_jni_headers',
+ ],
+ 'defines': [
+ 'UI_ANDROID_IMPLEMENTATION',
+ ],
+ 'sources' : [
+ 'resources/resource_manager.cc',
+ 'resources/resource_manager.h',
+ 'resources/ui_resource_android.cc',
+ 'resources/ui_resource_android.h',
+ 'ui_android_export.h',
+ 'ui_android_jni_registrar.cc',
+ 'ui_android_jni_registrar.h',
+ ],
+ },
+ {
+ 'target_name': 'ui_android_jni_headers',
+ 'type': 'none',
+ 'sources': [
+ 'java/src/org/chromium/ui/resources/ResourceManager.java',
+ ],
+ 'variables': {
+ 'jni_gen_package': 'ui_android',
+ },
+ 'includes': [ '../../build/jni_generator.gypi' ],
+ },
+ {
+ 'target_name': 'android_resource_type_java',
+ 'type': 'none',
+ 'variables': {
+ 'source_file': 'resources/resource_manager.h',
+ },
+ 'includes': [ '../../build/android/java_cpp_enum.gypi' ],
+ },
+ {
'target_name': 'bitmap_format_java',
'type': 'none',
'variables': {
@@ -58,6 +102,7 @@
},
'dependencies': [
'../../base/base.gyp:base_java',
+ 'android_resource_type_java',
'bitmap_format_java',
'page_transition_types_java',
'system_ui_resource_type_java',
diff --git a/ui/android/ui_android_export.h b/ui/android/ui_android_export.h
new file mode 100644
index 0000000..1beb2ef
--- /dev/null
+++ b/ui/android/ui_android_export.h
@@ -0,0 +1,31 @@
+// Copyright 2014 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 UI_ANDROID_UI_ANDROID_EXPORT_H_
+#define UI_ANDROID_UI_ANDROID_EXPORT_H_
+
+// Defines UI_ANDROID_EXPORT so that functionality implemented by the UI module
+// can be exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WIN32)
+#error Unsupported target architecture.
+#else // !defined(WIN32)
+
+#if defined(UI_ANDROID_IMPLEMENTATION)
+#define UI_ANDROID_EXPORT __attribute__((visibility("default")))
+#else
+#define UI_ANDROID_EXPORT
+#endif
+
+#endif
+
+#else // !defined(COMPONENT_BUILD)
+
+#define UI_ANDROID_EXPORT
+
+#endif
+
+#endif // UI_ANDROID_UI_ANDROID_EXPORT_H_
diff --git a/ui/android/ui_android_jni_registrar.cc b/ui/android/ui_android_jni_registrar.cc
new file mode 100644
index 0000000..e0e1fd6
--- /dev/null
+++ b/ui/android/ui_android_jni_registrar.cc
@@ -0,0 +1,22 @@
+// Copyright 2014 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 "ui/android/ui_android_jni_registrar.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_registrar.h"
+#include "ui/android/resources/resource_manager.h"
+
+namespace ui {
+
+static base::android::RegistrationMethod kAndroidRegisteredMethods[] = {
+ {"ResourceManager", ui::ResourceManager::RegisterResourceManager},
+};
+
+bool RegisterUIAndroidJni(JNIEnv* env) {
+ return RegisterNativeMethods(env, kAndroidRegisteredMethods,
+ arraysize(kAndroidRegisteredMethods));
+}
+
+} // namespace ui
diff --git a/ui/android/ui_android_jni_registrar.h b/ui/android/ui_android_jni_registrar.h
new file mode 100644
index 0000000..b1a5fd6
--- /dev/null
+++ b/ui/android/ui_android_jni_registrar.h
@@ -0,0 +1,19 @@
+// Copyright 2014 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 UI_ANDROID_UI_ANDROID_JNI_REGISTRAR_H_
+#define UI_ANDROID_UI_ANDROID_JNI_REGISTRAR_H_
+
+#include <jni.h>
+
+#include "ui/android/ui_android_export.h"
+
+namespace ui {
+
+// Register all JNI bindings necessary for chrome.
+UI_ANDROID_EXPORT bool RegisterUIAndroidJni(JNIEnv* env);
+
+} // namespace ui
+
+#endif // UI_ANDROID_UI_ANDROID_JNI_REGISTRAR_H_