diff options
43 files changed, 478 insertions, 89 deletions
diff --git a/base/message_loop.cc b/base/message_loop.cc index 5428026..0a6bf6c 100644 --- a/base/message_loop.cc +++ b/base/message_loop.cc @@ -251,9 +251,12 @@ void MessageLoop::EnableHistogrammer(bool enable) { } // static -void MessageLoop::InitMessagePumpForUIFactory(MessagePumpFactory* factory) { - DCHECK(!message_pump_for_ui_factory_); +bool MessageLoop::InitMessagePumpForUIFactory(MessagePumpFactory* factory) { + if (message_pump_for_ui_factory_) + return false; + message_pump_for_ui_factory_ = factory; + return true; } void MessageLoop::AddDestructionObserver( diff --git a/base/message_loop.h b/base/message_loop.h index 446a520..b690940 100644 --- a/base/message_loop.h +++ b/base/message_loop.h @@ -120,9 +120,10 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate { static void EnableHistogrammer(bool enable_histogrammer); typedef base::MessagePump* (MessagePumpFactory)(); - // Using the given base::MessagePumpForUIFactory to override the default - // MessagePump implementation for 'TYPE_UI'. - static void InitMessagePumpForUIFactory(MessagePumpFactory* factory); + // Uses the given base::MessagePumpForUIFactory to override the default + // MessagePump implementation for 'TYPE_UI'. Returns true if the factory + // was successfully registered. + static bool InitMessagePumpForUIFactory(MessagePumpFactory* factory); // A DestructionObserver is notified when the current MessageLoop is being // destroyed. These observers are notified prior to MessageLoop::current() diff --git a/base/test/test_support_android.cc b/base/test/test_support_android.cc index 8b512f4..e38a897 100644 --- a/base/test/test_support_android.cc +++ b/base/test/test_support_android.cc @@ -183,7 +183,8 @@ void InitAndroidTestPaths() { } void InitAndroidTestMessageLoop() { - MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub); + if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub)) + LOG(INFO) << "MessagePumpForUIFactory already set, unable to override."; } void InitAndroidTest() { diff --git a/build/android/adb_gdb_content_shell b/build/android/adb_gdb_content_shell index d0b6947..18e1a61 100755 --- a/build/android/adb_gdb_content_shell +++ b/build/android/adb_gdb_content_shell @@ -12,5 +12,5 @@ export ADB_GDB_PROGNAME=$(basename "$0") export ADB_GDB_ACTIVITY=.ContentShellActivity "$PROGDIR"/adb_gdb \ --program-name=ContentShell \ - --package-name=org.chromium.content_shell \ + --package-name=org.chromium.content_shell_apk \ "$@" diff --git a/build/android/adb_kill_content_shell b/build/android/adb_kill_content_shell index d24c7a9..64ab5b1 100755 --- a/build/android/adb_kill_content_shell +++ b/build/android/adb_kill_content_shell @@ -8,7 +8,7 @@ # # Assumes you have sourced the build/android/envsetup.sh script. -SHELL_PID_LINES=$(adb shell ps | grep ' org.chromium.content_shell') +SHELL_PID_LINES=$(adb shell ps | grep ' org.chromium.content_shell_apk') VAL=$(echo "$SHELL_PID_LINES" | wc -l) if [ $VAL -lt 1 ] ; then echo "Not running Content shell." diff --git a/build/android/adb_run_content_shell b/build/android/adb_run_content_shell index ea92f5a..17a734c 100755 --- a/build/android/adb_run_content_shell +++ b/build/android/adb_run_content_shell @@ -10,5 +10,5 @@ fi adb shell am start \ -a android.intent.action.VIEW \ - -n org.chromium.content_shell/.ContentShellActivity \ + -n org.chromium.content_shell_apk/.ContentShellActivity \ $INTENT_ARGS diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py index 98cd640..81e540b 100755 --- a/build/android/buildbot/bb_device_steps.py +++ b/build/android/buildbot/bb_device_steps.py @@ -41,7 +41,7 @@ I_TEST = collections.namedtuple('InstrumentationTest', [ INSTRUMENTATION_TESTS = dict((suite.name, suite) for suite in [ I_TEST('ContentShell', 'ContentShell.apk', - 'org.chromium.content_shell', + 'org.chromium.content_shell_apk', 'ContentShellTest', 'content:content/test/data/android/device_files'), I_TEST('ChromiumTestShell', diff --git a/build/android/gdb_apk b/build/android/gdb_apk index 7e657d6..41feae6 100755 --- a/build/android/gdb_apk +++ b/build/android/gdb_apk @@ -96,7 +96,7 @@ process_options() { rooted_phone=0 root=$(dirname $0)/../.. -package_name=org.chromium.content_shell +package_name=org.chromium.content_shell_apk shared_lib_dir=$root/out/${BUILDTYPE:-Debug}/lib.target gdb_args='' diff --git a/build/android/gdb_content_shell b/build/android/gdb_content_shell index c8cb88f..81a1986 100755 --- a/build/android/gdb_content_shell +++ b/build/android/gdb_content_shell @@ -12,5 +12,5 @@ adb_gdb_content_shell instead!" if [ $# -gt 0 ]; then exec ${ROOT}/gdb_apk -r -g "$*" else - exec ${ROOT}/gdb_apk -r -p org.chromium.content_shell + exec ${ROOT}/gdb_apk -r -p org.chromium.content_shell_apk fi diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py index a7845f1..ffcf325 100644 --- a/build/android/pylib/constants.py +++ b/build/android/pylib/constants.py @@ -12,8 +12,8 @@ CHROME_ACTIVITY = 'com.google.android.apps.chrome.Main' CHROME_TESTS_PACKAGE = 'com.google.android.apps.chrome.tests' LEGACY_BROWSER_PACKAGE = 'com.google.android.browser' LEGACY_BROWSER_ACTIVITY = 'com.android.browser.BrowserActivity' -CONTENT_SHELL_PACKAGE = "org.chromium.content_shell" -CONTENT_SHELL_ACTIVITY = "org.chromium.content_shell.ContentShellActivity" +CONTENT_SHELL_PACKAGE = "org.chromium.content_shell_apk" +CONTENT_SHELL_ACTIVITY = "org.chromium.content_shell_apk.ContentShellActivity" CHROME_SHELL_PACKAGE = 'org.chromium.chrome.browser.test' CHROMIUM_TEST_SHELL_PACKAGE = 'org.chromium.chrome.testshell' diff --git a/build/java_apk.gypi b/build/java_apk.gypi index a887663..fb79797 100644 --- a/build/java_apk.gypi +++ b/build/java_apk.gypi @@ -18,12 +18,10 @@ # 'includes': ['path/to/this/gypi/file'], # } # -# Note that this assumes that there's an ant buildfile <package_name>_apk.xml in -# java_in_dir. So, if you have package_name="content_shell" and +# If you have package_name="content_shell" and # java_in_dir="content/shell/android/java" you should have a directory structure # like: # -# content/shell/android/java/content_shell_apk.xml # content/shell/android/java/src/org/chromium/base/Foo.java # content/shell/android/java/src/org/chromium/base/Bar.java # @@ -41,8 +39,8 @@ # each directory in additional_res_dirs. # additional_src_dirs - Additional directories with .java files to be compiled # and included in the output of this target. -# asset_location - The directory where assets are located (default: -# <PRODUCT_DIR>/<package_name>/assets). +# asset_location - The absolute path to the directory where assets are located +# (default: <(ant_build_out)/<(package_name)/assets). # generated_src_dirs - Same as additional_src_dirs except used for .java files # that are generated at build time. This should be set automatically by a # target's dependencies. The .java files in these directories are not diff --git a/content/content.gyp b/content/content.gyp index 0155546..d15f86f 100644 --- a/content/content.gyp +++ b/content/content.gyp @@ -290,6 +290,7 @@ 'type': 'none', 'dependencies': [ '../base/base.gyp:base', + '../media/media.gyp:media_java', '../net/net.gyp:net', '../ui/ui.gyp:ui_java', 'common_aidl', diff --git a/content/content_shell.gypi b/content/content_shell.gypi index 62129cb..126c82f 100644 --- a/content/content_shell.gypi +++ b/content/content_shell.gypi @@ -53,6 +53,10 @@ '..', ], 'sources': [ + 'shell/android/shell_jni_registrar.cc', + 'shell/android/shell_jni_registrar.h', + 'shell/android/shell_manager.cc', + 'shell/android/shell_manager.h', 'shell/geolocation/shell_access_token_store.cc', 'shell/geolocation/shell_access_token_store.h', 'shell/minimal_ash.cc', @@ -558,6 +562,7 @@ 'target_name': 'content_shell_jni_headers', 'type': 'none', 'sources': [ + 'shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java', 'shell/android/java/src/org/chromium/content_shell/ShellManager.java', 'shell/android/java/src/org/chromium/content_shell/Shell.java', ], @@ -586,12 +591,6 @@ 'sources': [ 'shell/android/shell_library_loader.cc', 'shell/android/shell_library_loader.h', - 'shell/android/shell_manager.cc', - 'shell/android/shell_manager.h', - ], - 'sources!': [ - 'shell/shell_main.cc', - 'shell/shell_main.h', ], 'conditions': [ ['android_build_type==1', { @@ -602,11 +601,27 @@ ], }, { + 'target_name': 'content_shell_java', + 'type': 'none', + 'dependencies': [ + 'content_java', + ], + 'variables': { + 'package_name': 'content_shell', + 'java_in_dir': '../content/shell/android/java', + 'has_java_resources': 1, + 'R_package': 'org.chromium.content_shell', + 'R_package_relpath': 'org/chromium/content_shell', + }, + 'includes': [ '../build/java.gypi' ], + }, + { # content_shell_apk creates a .jar as a side effect. Any java targets # that need that .jar in their classpath should depend on this target, - # content_shell_java. Dependents of content_shell_apk receive its jar - # path in the variable 'apk_output_jar_path'. - 'target_name': 'content_shell_java', + # content_shell_apk_java. Dependents of content_shell_apk receive its + # jar path in the variable 'apk_output_jar_path'. This target should + # only be used by targets which instrument content_shell_apk. + 'target_name': 'content_shell_apk_java', 'type': 'none', 'dependencies': [ 'content_shell_apk', @@ -635,21 +650,22 @@ 'type': 'none', 'dependencies': [ 'content_java', + 'content_shell_java', + 'libcontent_shell_content_view', '../base/base.gyp:base_java', '../media/media.gyp:media_java', '../net/net.gyp:net_java', '../ui/ui.gyp:ui_java', ], 'variables': { - 'package_name': 'content_shell', + 'package_name': 'content_shell_apk', 'apk_name': 'ContentShell', - 'manifest_package_name': 'org.chromium.content_shell', - 'java_in_dir': 'shell/android/java', - # TODO(cjhopman): The resource directory of all apks should be in - # <java_in_dir>/res. - 'resource_dir': '../res', + 'manifest_package_name': 'org.chromium.content_shell_apk', + 'java_in_dir': 'shell/android/shell_apk', + 'resource_dir': 'res', 'native_libs_paths': ['<(SHARED_LIB_DIR)/libcontent_shell_content_view.so'], 'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'], + 'asset_location': '<(ant_build_out)/content_shell/assets', }, 'includes': [ '../build/java_apk.gypi' ], }, diff --git a/content/content_tests.gypi b/content/content_tests.gypi index b0b03f0..3d57f51 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -821,13 +821,11 @@ 'common/content_constants_internal.h', ], 'sources': [ - 'shell/android/shell_library_loader.cc', - 'shell/android/shell_library_loader.cc', - 'shell/android/shell_manager.cc', - 'shell/android/shell_manager.h', + 'shell/android/browsertests_apk/content_browser_tests_android.cc', ], 'dependencies': [ 'content_shell_jni_headers', + 'content_shell_lib', ], }], ['OS=="mac"', { @@ -966,6 +964,25 @@ }, 'includes': [ '../build/apk_test.gypi' ], }, + { + 'target_name': 'content_browsertests_apk', + 'type': 'none', + 'dependencies': [ + 'content_browsertests', + 'content_java', + 'content_shell_java', + ], + 'variables': { + 'package_name': 'content_browsertests_apk', + 'apk_name': 'content_browsertests', + 'java_in_dir': 'shell/android/browsertests_apk', + 'resource_dir': 'res', + 'native_libs_paths': ['<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)content_browsertests<(SHARED_LIB_SUFFIX)'], + 'additional_input_paths': ['<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'], + 'asset_location': '<(ant_build_out)/content_shell/assets', + }, + 'includes': [ '../build/java_apk.gypi' ], + }, ], }], ['OS == "android"', { @@ -991,7 +1008,7 @@ 'dependencies': [ 'content_java', 'content_java_test_support', - 'content_shell_java', + 'content_shell_apk_java', '../base/base.gyp:base_java', '../base/base.gyp:base_java_test_support', '../media/media.gyp:media_java', @@ -1004,8 +1021,8 @@ 'package_name': 'content_shell_test', 'apk_name': 'ContentShellTest', 'java_in_dir': '../content/shell/android/javatests', - 'resource_dir': '../res', - 'additional_src_dirs': ['../content/public/android/javatests/'], + 'additional_src_dirs': ['../content/public/android/javatests/',], + 'resource_dir': '../shell_apk/res', 'is_test_apk': 1, }, 'includes': [ '../build/java_apk.gypi' ], diff --git a/content/public/android/javatests/src/org/chromium/content/browser/CommandLineTest.java b/content/public/android/javatests/src/org/chromium/content/browser/CommandLineTest.java index b84f7b8..96015f9 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/CommandLineTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/CommandLineTest.java @@ -12,8 +12,8 @@ import org.chromium.base.test.util.Feature; import org.chromium.content.app.LibraryLoader; import org.chromium.content.common.CommandLine; import org.chromium.content.common.ProcessInitException; -import org.chromium.content_shell.ContentShellActivity; -import org.chromium.content_shell.ContentShellApplication; +import org.chromium.content_shell_apk.ContentShellActivity; +import org.chromium.content_shell_apk.ContentShellApplication; public class CommandLineTest extends InstrumentationTestCase { // A reference command line. Note that switch2 is [brea\d], switch3 is [and "butter"], diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java index d07c514..a54c551 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java @@ -15,7 +15,6 @@ import org.chromium.content.browser.test.util.JavaScriptUtils; import org.chromium.content.browser.test.util.TestCallbackHelperContainer; import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper; import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnStartContentIntentHelper; -import org.chromium.content_shell.ContentShellActivity; import org.chromium.content_shell.ContentShellTestBase; /** diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewTestBase.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewTestBase.java index 66d7f62..a95165f 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewTestBase.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewTestBase.java @@ -7,8 +7,8 @@ package org.chromium.content.browser; import android.util.Log; import org.chromium.content.browser.test.util.TestCallbackHelperContainer; -import org.chromium.content_shell.ContentShellActivity; import org.chromium.content_shell.ContentShellTestBase; +import org.chromium.content_shell_apk.ContentShellActivity; public class ContentViewTestBase extends ContentShellTestBase { diff --git a/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java b/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java index 177fa6e..7ad9162 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/InterstitialPageTest.java @@ -12,8 +12,8 @@ import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.TouchCommon; import org.chromium.content.browser.test.util.UiUtils; -import org.chromium.content_shell.ContentShellActivity; import org.chromium.content_shell.ContentShellTestBase; +import org.chromium.content_shell_apk.ContentShellActivity; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; diff --git a/content/public/android/javatests/src/org/chromium/content/browser/NavigationTest.java b/content/public/android/javatests/src/org/chromium/content/browser/NavigationTest.java index d223b60..836db69 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/NavigationTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/NavigationTest.java @@ -8,8 +8,8 @@ import android.test.suitebuilder.annotation.MediumTest; import org.chromium.base.test.util.Feature; import org.chromium.content.browser.test.util.TestCallbackHelperContainer; -import org.chromium.content_shell.ContentShellActivity; import org.chromium.content_shell.ContentShellTestBase; +import org.chromium.content_shell_apk.ContentShellActivity; /** * Tests for various aspects of navigation. diff --git a/content/public/test/content_test_suite_base.cc b/content/public/test/content_test_suite_base.cc index 0c32858..7c8c4d3 100644 --- a/content/public/test/content_test_suite_base.cc +++ b/content/public/test/content_test_suite_base.cc @@ -15,6 +15,14 @@ #include "ui/base/ui_base_paths.h" #include "ui/compositor/compositor_setup.h" +#if defined(OS_ANDROID) +#include "base/android/jni_android.h" +#include "content/browser/android/browser_jni_registrar.h" +#include "content/common/android/common_jni_registrar.h" +#include "net/android/net_jni_registrar.h" +#include "ui/android/ui_jni_registrar.h" +#endif + namespace content { ContentTestSuiteBase::ContentTestSuiteBase(int argc, char** argv) @@ -25,6 +33,15 @@ ContentTestSuiteBase::ContentTestSuiteBase(int argc, char** argv) void ContentTestSuiteBase::Initialize() { base::TestSuite::Initialize(); +#if defined(OS_ANDROID) + // Register JNI bindings for android. + JNIEnv* env = base::android::AttachCurrentThread(); + content::android::RegisterCommonJni(env); + content::android::RegisterBrowserJni(env); + net::android::RegisterJni(env); + ui::android::RegisterJni(env); +#endif + if (external_libraries_enabled_) media::InitializeMediaLibraryForTesting(); diff --git a/content/shell/android/browsertests_apk/AndroidManifest.xml b/content/shell/android/browsertests_apk/AndroidManifest.xml new file mode 100644 index 0000000..5746a43 --- /dev/null +++ b/content/shell/android/browsertests_apk/AndroidManifest.xml @@ -0,0 +1,72 @@ +<?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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.chromium.content_browsertests_apk"> + + <permission android:name="org.chromium.content_shell.permission.SANDBOX" + android:protectionLevel="signature" /> + + <application android:name="ContentBrowserTestsApplication" + android:label="ContentBrowserTests"> + <activity android:name="ContentBrowserTestsActivity" + android:launchMode="singleTask" + android:theme="@android:style/Theme.Holo.Light.NoActionBar" + android:configChanges="orientation|keyboardHidden|keyboard|screenSize" + android:hardwareAccelerated="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + <!-- The following service entries exist in order to allow us to + start more than one sandboxed process. --> + + <!-- NOTE: If you change the values of "android:process" for any of the below services, + you also need to update kHelperProcessExecutableName in chrome_constants.cc. --> + <service android:name="org.chromium.content.app.SandboxedProcessService0" + android:process=":sandboxed_process0" + android:permission="org.chromium.content_shell.permission.SANDBOX" + android:isolatedProcess="true" + android:exported="false" /> + <service android:name="org.chromium.content.app.SandboxedProcessService1" + android:process=":sandboxed_process1" + android:permission="org.chromium.content_shell.permission.SANDBOX" + android:isolatedProcess="true" + android:exported="false" /> + <service android:name="org.chromium.content.app.SandboxedProcessService2" + android:process=":sandboxed_process2" + android:permission="org.chromium.content_shell.permission.SANDBOX" + android:isolatedProcess="true" + android:exported="false" /> + <service android:name="org.chromium.content.app.SandboxedProcessService3" + android:process=":sandboxed_process3" + android:permission="org.chromium.content_shell.permission.SANDBOX" + android:isolatedProcess="true" + android:exported="false" /> + <service android:name="org.chromium.content.app.SandboxedProcessService4" + android:process=":sandboxed_process4" + android:permission="org.chromium.content_shell.permission.SANDBOX" + android:isolatedProcess="true" + android:exported="false" /> + <service android:name="org.chromium.content.app.SandboxedProcessService5" + android:process=":sandboxed_process5" + android:permission="org.chromium.content_shell.permission.SANDBOX" + android:isolatedProcess="true" + android:exported="false" /> + </application> + + <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.VIBRATE"/> + <uses-permission android:name="android.permission.READ_PHONE_STATE"/> + <uses-permission android:name="android.permission.WAKE_LOCK"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> +</manifest> diff --git a/content/shell/android/browsertests_apk/content_browser_tests_android.cc b/content/shell/android/browsertests_apk/content_browser_tests_android.cc new file mode 100644 index 0000000..4ed222d4 --- /dev/null +++ b/content/shell/android/browsertests_apk/content_browser_tests_android.cc @@ -0,0 +1,127 @@ +// 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. + +// This class sets up the environment for running the content browser tests +// inside an android application. + +#include <android/log.h> + +#include "base/android/base_jni_registrar.h" +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/string_tokenizer.h" +#include "base/string_util.h" +#include "base/stringprintf.h" +#include "content/public/app/android_library_loader_hooks.h" +#include "content/shell/android/shell_jni_registrar.h" +#include "jni/ContentBrowserTestsActivity_jni.h" + +// The main function of the program to be wrapped as an apk. +extern int main(int argc, char** argv); + +namespace { + +void ParseArgsFromString(const std::string& command_line, + std::vector<std::string>* args) { + StringTokenizer tokenizer(command_line, kWhitespaceASCII); + tokenizer.set_quote_chars("\""); + while (tokenizer.GetNext()) { + std::string token; + RemoveChars(tokenizer.token(), "\"", &token); + args->push_back(token); + } +} + +void ParseArgsFromCommandLineFile(std::vector<std::string>* args) { + // The test runner script writes the command line file in + // "/data/local/tmp". + static const char kCommandLineFilePath[] = + "/data/local/tmp/content-browser-tests-command-line"; + FilePath command_line(kCommandLineFilePath); + std::string command_line_string; + if (file_util::ReadFileToString(command_line, &command_line_string)) { + ParseArgsFromString(command_line_string, args); + } +} + +int ArgsToArgv(const std::vector<std::string>& args, + std::vector<char*>* argv) { + // We need to pass in a non-const char**. + int argc = args.size(); + + argv->resize(argc + 1); + for (int i = 0; i < argc; ++i) + (*argv)[i] = const_cast<char*>(args[i].c_str()); + (*argv)[argc] = NULL; // argv must be NULL terminated. + + return argc; +} + +class ScopedMainEntryLogger { + public: + ScopedMainEntryLogger() { + printf(">>ScopedMainEntryLogger\n"); + } + + ~ScopedMainEntryLogger() { + printf("<<ScopedMainEntryLogger\n"); + fflush(stdout); + fflush(stderr); + } +}; + +} // namespace + +static void RunTests(JNIEnv* env, + jobject obj, + jstring jfiles_dir, + jobject app_context) { + + // Command line basic initialization, will be fully initialized later. + static const char* const kInitialArgv[] = { "ContentBrowserTestsActivity" }; + CommandLine::Init(arraysize(kInitialArgv), kInitialArgv); + + // Set the application context in base. + base::android::ScopedJavaLocalRef<jobject> scoped_context( + env, env->NewLocalRef(app_context)); + base::android::InitApplicationContext(scoped_context); + base::android::RegisterJni(env); + + std::vector<std::string> args; + ParseArgsFromCommandLineFile(&args); + + // We need to pass in a non-const char**. + std::vector<char*> argv; + int argc = ArgsToArgv(args, &argv); + + // Fully initialize command line with arguments. + CommandLine::ForCurrentProcess()->AppendArguments( + CommandLine(argc, &argv[0]), false); + + ScopedMainEntryLogger scoped_main_entry_logger; + main(argc, &argv[0]); +} + +// This is called by the VM when the shared library is first loaded. +JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + base::android::InitVM(vm); + JNIEnv* env = base::android::AttachCurrentThread(); + + if (!content::RegisterLibraryLoaderEntryHook(env)) + return -1; + + if (!content::android::RegisterShellJni(env)) + return -1; + + if (!RegisterNativesImpl(env)) + return -1; + + return JNI_VERSION_1_4; +} diff --git a/content/shell/android/res/layout/content_shell_activity.xml b/content/shell/android/browsertests_apk/res/layout/test_activity.xml index c62e66e..c62e66e 100644 --- a/content/shell/android/res/layout/content_shell_activity.xml +++ b/content/shell/android/browsertests_apk/res/layout/test_activity.xml diff --git a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java new file mode 100644 index 0000000..6c7f09a --- /dev/null +++ b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java @@ -0,0 +1,46 @@ +// 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.content_browsertests_apk; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import org.chromium.content.app.LibraryLoader; +import org.chromium.content.common.ProcessInitException; +import org.chromium.ui.gfx.ActivityNativeWindow; +import org.chromium.content_shell.ShellManager; + +public class ContentBrowserTestsActivity extends Activity { + private static final String TAG = "ChromeBrowserTestsActivity"; + + private ShellManager mShellManager; + private ActivityNativeWindow mActivityNativeWindow; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + try { + LibraryLoader.ensureInitialized(); + } catch (ProcessInitException e) { + Log.i(TAG, "Cannot load content_browsertests:" + e); + } + + setContentView(R.layout.test_activity); + mShellManager = (ShellManager) findViewById(R.id.shell_container); + mActivityNativeWindow = new ActivityNativeWindow(this); + mShellManager.setWindow(mActivityNativeWindow); + + runTests(); + } + + private void runTests() { + nativeRunTests(getFilesDir().getAbsolutePath(), getApplicationContext()); + } + + private native void nativeRunTests(String filesDir, Context appContext); +} diff --git a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsApplication.java b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsApplication.java new file mode 100644 index 0000000..315a17e --- /dev/null +++ b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsApplication.java @@ -0,0 +1,31 @@ +// 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.content_browsertests_apk; + +import android.app.Application; + +import org.chromium.base.PathUtils; +import org.chromium.content.app.LibraryLoader; +import org.chromium.content.browser.ResourceExtractor; + +public class ContentBrowserTestsApplication extends Application { + + private static final String NATIVE_LIBRARY = "content_browsertests"; + private static final String[] MANDATORY_PAK_FILES = new String[] {"content_shell.pak"}; + private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "content_shell"; + + @Override + public void onCreate() { + super.onCreate(); + initializeApplicationParameters(); + } + + public static void initializeApplicationParameters() { + ResourceExtractor.setMandatoryPaksToExtract(MANDATORY_PAK_FILES); + LibraryLoader.setLibraryToLoad(NATIVE_LIBRARY); + PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX); + } + +} diff --git a/content/shell/android/res/drawable/progress.xml b/content/shell/android/java/res/drawable/progress.xml index 93322b9..93322b9 100644 --- a/content/shell/android/res/drawable/progress.xml +++ b/content/shell/android/java/res/drawable/progress.xml diff --git a/content/shell/android/res/layout/shell_view.xml b/content/shell/android/java/res/layout/shell_view.xml index d6c15d6..d6c15d6 100644 --- a/content/shell/android/res/layout/shell_view.xml +++ b/content/shell/android/java/res/layout/shell_view.xml diff --git a/content/shell/android/res/values/strings.xml b/content/shell/android/java/res/values/strings.xml index 6eaaaec..6eaaaec 100644 --- a/content/shell/android/res/values/strings.xml +++ b/content/shell/android/java/res/values/strings.xml diff --git a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java index 4cc0906..7cf962d 100644 --- a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java +++ b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java @@ -21,11 +21,12 @@ import org.chromium.ui.gfx.NativeWindow; @JNINamespace("content") public class ShellManager extends FrameLayout { + public static final String DEFAULT_SHELL_URL = "http://www.google.com"; private static boolean sStartup = true; private NativeWindow mWindow; private Shell mActiveShell; - private String mStartupUrl = ContentShellActivity.DEFAULT_SHELL_URL; + private String mStartupUrl = DEFAULT_SHELL_URL; // The target for all content rendering. private ContentViewRenderView mContentViewRenderView; @@ -71,7 +72,7 @@ public class ShellManager extends FrameLayout { /** * @return The currently visible shell view or null if one is not showing. */ - protected Shell getActiveShell() { + public Shell getActiveShell() { return mActiveShell; } diff --git a/content/shell/android/javatests/AndroidManifest.xml b/content/shell/android/javatests/AndroidManifest.xml index fcd2465..3f27e60 100644 --- a/content/shell/android/javatests/AndroidManifest.xml +++ b/content/shell/android/javatests/AndroidManifest.xml @@ -5,7 +5,7 @@ <!-- package name must be unique so suffix with "tests" so package loader doesn't ignore this. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="org.chromium.content_shell.tests"> + package="org.chromium.content_shell_apk.tests"> <!-- We add an application tag here just so that we can indicate that this package needs to link against the android.test library, which is needed when building test cases. --> @@ -14,8 +14,8 @@ </application> <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> <instrumentation android:name="android.test.InstrumentationTestRunner" - android:targetPackage="org.chromium.content_shell" - android:label="Tests for org.chromium.content_shell"/> + android:targetPackage="org.chromium.content_shell_apk" + android:label="Tests for org.chromium.content_shell_apk"/> <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> <uses-permission android:name="android.permission.INJECT_EVENTS" /> </manifest> diff --git a/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellTestBase.java b/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellTestBase.java index 23637df..f4d7a2f 100644 --- a/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellTestBase.java +++ b/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellTestBase.java @@ -18,6 +18,7 @@ import org.chromium.content.browser.test.util.CallbackHelper; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.TestCallbackHelperContainer; +import org.chromium.content_shell_apk.ContentShellActivity; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellUrlTest.java b/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellUrlTest.java index 05eba42..98b06c1 100644 --- a/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellUrlTest.java +++ b/content/shell/android/javatests/src/org/chromium/content_shell/ContentShellUrlTest.java @@ -7,6 +7,7 @@ package org.chromium.content_shell; import android.test.suitebuilder.annotation.SmallTest; import org.chromium.base.test.util.Feature; +import org.chromium.content_shell_apk.ContentShellActivity; /** * Example test that just starts the content shell. diff --git a/content/shell/android/java/AndroidManifest.xml b/content/shell/android/shell_apk/AndroidManifest.xml index cfeb0c4..77444a3 100644 --- a/content/shell/android/java/AndroidManifest.xml +++ b/content/shell/android/shell_apk/AndroidManifest.xml @@ -7,7 +7,7 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="org.chromium.content_shell"> + package="org.chromium.content_shell_apk"> <permission android:name="org.chromium.content_shell.permission.SANDBOX" android:protectionLevel="signature" /> diff --git a/content/shell/android/shell_apk/res/layout/content_shell_activity.xml b/content/shell/android/shell_apk/res/layout/content_shell_activity.xml new file mode 100644 index 0000000..c62e66e --- /dev/null +++ b/content/shell/android/shell_apk/res/layout/content_shell_activity.xml @@ -0,0 +1,14 @@ +<?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. + --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <org.chromium.content_shell.ShellManager + android:id="@+id/shell_container" + android:layout_width="match_parent" + android:layout_height="match_parent" /> +</merge> diff --git a/content/shell/android/java/src/org/chromium/content_shell/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java index cd3e546..0ce99d8 100644 --- a/content/shell/android/java/src/org/chromium/content_shell/ContentShellActivity.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.content_shell; +package org.chromium.content_shell_apk; import android.app.Activity; import android.content.BroadcastReceiver; @@ -23,6 +23,8 @@ import org.chromium.content.browser.DeviceUtils; import org.chromium.content.browser.TracingIntentHandler; import org.chromium.content.common.CommandLine; import org.chromium.content.common.ProcessInitException; +import org.chromium.content_shell.Shell; +import org.chromium.content_shell.ShellManager; import org.chromium.ui.gfx.ActivityNativeWindow; /** @@ -38,7 +40,6 @@ public class ContentShellActivity extends ChromiumActivity { "org.chromium.content_shell.action.PROFILE_START"; private static final String ACTION_STOP_TRACE = "org.chromium.content_shell.action.PROFILE_STOP"; - public static final String DEFAULT_SHELL_URL = "http://www.google.com"; public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs"; private ShellManager mShellManager; @@ -76,7 +77,7 @@ public class ContentShellActivity extends ChromiumActivity { mShellManager.setStartupUrl(Shell.sanitizeUrl(startupUrl)); } if (!ContentView.enableMultiProcess(this, ContentView.MAX_RENDERERS_AUTOMATIC)) { - String shellUrl = DEFAULT_SHELL_URL; + String shellUrl = ShellManager.DEFAULT_SHELL_URL; if (savedInstanceState != null && savedInstanceState.containsKey(ACTIVE_SHELL_URL_KEY)) { shellUrl = savedInstanceState.getString(ACTIVE_SHELL_URL_KEY); diff --git a/content/shell/android/java/src/org/chromium/content_shell/ContentShellApplication.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellApplication.java index 16f7c51..d070fb0 100644 --- a/content/shell/android/java/src/org/chromium/content_shell/ContentShellApplication.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellApplication.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.content_shell; +package org.chromium.content_shell_apk; import android.app.Application; diff --git a/content/shell/android/shell_jni_registrar.cc b/content/shell/android/shell_jni_registrar.cc new file mode 100644 index 0000000..504eda7 --- /dev/null +++ b/content/shell/android/shell_jni_registrar.cc @@ -0,0 +1,30 @@ +// 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 "content/shell/android/shell_jni_registrar.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "content/shell/android/shell_manager.h" +#include "content/shell/shell.h" + +namespace { + +static base::android::RegistrationMethod kShellRegistrationMethods[] = { + { "Shell", content::Shell::Register }, + { "ShellManager", content::RegisterShellManager }, +}; + +} // namespace + +namespace content { +namespace android { + +bool RegisterShellJni(JNIEnv* env) { + return RegisterNativeMethods(env, kShellRegistrationMethods, + arraysize(kShellRegistrationMethods)); +} + +} // namespace android +} // namespace content diff --git a/content/shell/android/shell_jni_registrar.h b/content/shell/android/shell_jni_registrar.h new file mode 100644 index 0000000..f336c52 --- /dev/null +++ b/content/shell/android/shell_jni_registrar.h @@ -0,0 +1,19 @@ +// 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 CONTENT_SHELL_ANDROID_SHELL_JNI_REGISTRAR_H_ +#define CONTENT_SHELL_ANDROID_SHELL_JNI_REGISTRAR_H_ + +#include <jni.h> + +namespace content { +namespace android { + +// Register all JNI bindings necessary for content shell. +bool RegisterShellJni(JNIEnv* env); + +} // namespace android +} // namespace content + +#endif // CONTENT_SHELL_ANDROID_SHELL_JNI_REGISTRAR_H_ diff --git a/content/shell/android/shell_library_loader.cc b/content/shell/android/shell_library_loader.cc index 88262c9..f320387f 100644 --- a/content/shell/android/shell_library_loader.cc +++ b/content/shell/android/shell_library_loader.cc @@ -10,31 +10,23 @@ #include "content/public/app/android_library_loader_hooks.h" #include "content/public/app/content_main.h" #include "content/public/browser/android/compositor.h" -#include "content/shell/android/shell_manager.h" -#include "content/shell/shell.h" +#include "content/shell/android/shell_jni_registrar.h" #include "content/shell/shell_main_delegate.h" -static base::android::RegistrationMethod kRegistrationMethods[] = { - { "Shell", content::Shell::Register }, - { "ShellManager", content::RegisterShellManager }, -}; - // This is called by the VM when the shared library is first loaded. JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { base::android::InitVM(vm); JNIEnv* env = base::android::AttachCurrentThread(); + if (!content::RegisterLibraryLoaderEntryHook(env)) return -1; // To be called only from the UI thread. If loading the library is done on // a separate thread, this should be moved elsewhere. - if (!base::android::RegisterNativeMethods(env, kRegistrationMethods, - arraysize(kRegistrationMethods))) + if (!content::android::RegisterShellJni(env)) return -1; content::Compositor::Initialize(); - content::SetContentMainDelegate(new content::ShellMainDelegate()); - return JNI_VERSION_1_4; } diff --git a/content/test/content_test_launcher.cc b/content/test/content_test_launcher.cc index 5eebd690..a34db6b 100644 --- a/content/test/content_test_launcher.cc +++ b/content/test/content_test_launcher.cc @@ -17,6 +17,11 @@ #include "content/shell/shell_switches.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_ANDROID) +#include "base/message_loop.h" +#include "base/message_pump_android.h" +#endif + #if defined(OS_WIN) #include "content/public/app/startup_helper_win.h" #include "sandbox/win/src/sandbox_types.h" @@ -52,6 +57,12 @@ class ContentShellTestSuiteInitializer DISALLOW_COPY_AND_ASSIGN(ContentShellTestSuiteInitializer); }; +#if defined(OS_ANDROID) +base::MessagePump* CreateMessagePumpForUI() { + return new base::MessagePumpForUI(); +}; +#endif + class ContentBrowserTestSuite : public ContentTestSuiteBase { public: ContentBrowserTestSuite(int argc, char** argv) @@ -62,6 +73,14 @@ class ContentBrowserTestSuite : public ContentTestSuiteBase { protected: virtual void Initialize() OVERRIDE { + +#if defined(OS_ANDROID) + // This needs to be done before base::TestSuite::Initialize() is called, + // as it also tries to set MessagePumpForUIFactory. + if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUI)) + LOG(INFO) << "MessagePumpForUIFactory already set, unable to override."; +#endif + ContentTestSuiteBase::Initialize(); testing::TestEventListeners& listeners = diff --git a/content/test/run_all_unittests.cc b/content/test/run_all_unittests.cc index 58de889..695cebe 100644 --- a/content/test/run_all_unittests.cc +++ b/content/test/run_all_unittests.cc @@ -5,25 +5,7 @@ #include "content/test/content_test_suite.h" #include "content/public/test/unittest_test_suite.h" -#if defined(OS_ANDROID) -#include "base/android/jni_android.h" -#include "content/browser/android/browser_jni_registrar.h" -#include "content/common/android/common_jni_registrar.h" -#include "net/android/net_jni_registrar.h" -#include "ui/android/ui_jni_registrar.h" -#endif - int main(int argc, char** argv) { - -#if defined(OS_ANDROID) - // Register JNI bindings for android. - JNIEnv* env = base::android::AttachCurrentThread(); - content::android::RegisterCommonJni(env); - content::android::RegisterBrowserJni(env); - net::android::RegisterJni(env); - ui::android::RegisterJni(env); -#endif - return content::UnitTestTestSuite( new content::ContentTestSuite(argc, argv)).Run(); } diff --git a/tools/telemetry/telemetry/android_browser_finder.py b/tools/telemetry/telemetry/android_browser_finder.py index f2d12ba..37c0b99 100644 --- a/tools/telemetry/telemetry/android_browser_finder.py +++ b/tools/telemetry/telemetry/android_browser_finder.py @@ -29,8 +29,8 @@ CHROME_ACTIVITY = 'com.google.android.apps.chrome.Main' CHROME_COMMAND_LINE = '/data/local/chrome-command-line' CHROME_DEVTOOLS_REMOTE_PORT = 'localabstract:chrome_devtools_remote' -CONTENT_SHELL_PACKAGE = 'org.chromium.content_shell' -CONTENT_SHELL_ACTIVITY = 'org.chromium.content_shell.ContentShellActivity' +CONTENT_SHELL_PACKAGE = 'org.chromium.content_shell_apk' +CONTENT_SHELL_ACTIVITY = 'org.chromium.content_shell_apk.ContentShellActivity' CONTENT_SHELL_COMMAND_LINE = '/data/local/tmp/content-shell-command-line' CONTENT_SHELL_DEVTOOLS_REMOTE_PORT = ( 'localabstract:content_shell_devtools_remote') diff --git a/tools/telemetry/telemetry/android_browser_finder_unittest.py b/tools/telemetry/telemetry/android_browser_finder_unittest.py index ef1c75b..1d70e52 100644 --- a/tools/telemetry/telemetry/android_browser_finder_unittest.py +++ b/tools/telemetry/telemetry/android_browser_finder_unittest.py @@ -79,7 +79,7 @@ class AndroidBrowserFinderTest(unittest.TestCase): assert args[0] == 'pm' assert args[1] == 'list' assert args[2] == 'packages' - return ['package:org.chromium.content_shell', + return ['package:org.chromium.content_shell_apk', 'package.com.google.android.setupwizard'] self._stubs.adb_commands.shell_command_handlers['pm'] = OnPM |