Upstream version 10.38.217.0 87/28387/1
authorEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Mon, 6 Oct 2014 13:49:55 +0000 (13:49 +0000)
committerEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Mon, 6 Oct 2014 13:49:55 +0000 (13:49 +0000)
Upstream commit-id 025fc90b6c5d17d2ae84beda0cd8426fd415ce7c

Change-Id: I8ecf263b86d785d4cbcca1a3510bd89f3aa632d0
Signed-off-by: Eurogiciel-BOT <eurogiciel.tizen@gmail.com>
46 files changed:
packaging/crosswalk.spec
src/content/renderer/render_view_impl.cc
src/media/audio/pulse/pulse.sigs
src/media/audio/pulse/pulse_util.cc
src/ozone/patches/0008-Fix-crash-when-switching-to-console-VT-mode.patch [new file with mode: 0644]
src/ozone/ui/desktop_aura/desktop_window_tree_host_wayland.cc
src/ui/gl/gl_context_egl.cc
src/xwalk/DEPS.xwalk
src/xwalk/VERSION
src/xwalk/app/android/runtime_activity/src/org/xwalk/app/XWalkRuntimeActivityBase.java
src/xwalk/app/tools/android/customize.py
src/xwalk/app/tools/android/make_apk.py
src/xwalk/app/tools/android/make_apk_test.py
src/xwalk/app/tools/android/manifest_json_parser.py
src/xwalk/application/browser/application_tizen.cc
src/xwalk/application/browser/application_tizen.h
src/xwalk/application/browser/linux/running_application_object.cc
src/xwalk/application/common/tizen/application_storage_impl.cc
src/xwalk/application/common/tizen/package_query.cc
src/xwalk/application/tools/tizen/xwalk_platform_installer.cc
src/xwalk/application/tools/tizen/xwalk_platform_installer.h
src/xwalk/packaging/crosswalk.spec
src/xwalk/runtime/android/core/src/org/xwalk/core/SharedXWalkView.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/ReflectionHelper.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContentsClientBridge.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkUIClientInternal.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkViewDelegate.java
src/xwalk/runtime/browser/android/xwalk_content.cc
src/xwalk/runtime/browser/android/xwalk_contents_client_bridge.cc
src/xwalk/runtime/browser/android/xwalk_contents_client_bridge.h
src/xwalk/runtime/browser/android/xwalk_icon_helper.cc [new file with mode: 0644]
src/xwalk/runtime/browser/android/xwalk_icon_helper.h [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnFullscreenToggledTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnJavascriptModalDialogTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnPageLoadStartedTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnPageLoadStoppedTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnUnhandledKeyEventTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OpenFileChooserTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/ShouldOverrideKeyEventTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/TestHelperBridge.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/XWalkViewTestBase.java
src/xwalk/test/android/data/file_chooser.html [new file with mode: 0644]
src/xwalk/test/android/data/fullscreen_togged.html [new file with mode: 0644]
src/xwalk/test/android/data/js_modal_dialog.html [new file with mode: 0644]
src/xwalk/xwalk.gyp
src/xwalk/xwalk_android_tests.gypi

index b8c576a..88d9c84 100644 (file)
@@ -16,7 +16,7 @@
 %endif
 
 Name:           crosswalk
-Version:        10.38.212.0
+Version:        10.38.217.0
 Release:        0
 Summary:        Chromium-based app runtime
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -140,6 +140,13 @@ cp -a src/xwalk/LICENSE LICENSE.xwalk
 
 %build
 
+# Stop unconditionally passing -Wall to the compiler. Chromium has its own
+# mechanisms for deciding which parts of the code need -Wall and which need it
+# to be left out (since several pieces are built with -Werror). At least in
+# M39, this is preventing the "rtc_base" target from being built because it
+# does not expect -Wall to be passed to the compiler (see webrtc issue 3307).
+export CXXFLAGS=`echo $CXXFLAGS | sed s,-Wall,,g`
+
 # For ffmpeg on ia32. The original CFLAGS set by the gyp and config files in
 # src/third_party/ffmpeg already pass -O2 -fomit-frame-pointer, but Tizen's
 # CFLAGS end up appending -fno-omit-frame-pointer. See http://crbug.com/37246
index 671ed9e..9e4ac4a 100644 (file)
@@ -1138,6 +1138,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
 
   // Enable double tap to zoom when zoomable.
   settings->setDoubleTapToZoomEnabled(true);
+
+  settings->setShrinksViewportContentToFit(true);
 #endif
 
 #if defined(OS_ANDROID)
index 45718b9..8d2dab7 100644 (file)
@@ -50,8 +50,3 @@ void pa_stream_unref(pa_stream* s);
 int pa_context_errno(pa_context *c);
 const char* pa_strerror(int error);
 pa_cvolume* pa_cvolume_set(pa_cvolume* a, unsigned  channels, pa_volume_t v);
-# Functions from pulse used in TIZEN to tag the audio stream as "browser".
-pa_proplist* pa_proplist_new(void);
-void pa_proplist_free(pa_proplist* p);
-int pa_proplist_sets(pa_proplist *p, const char *key, const char *value);
-pa_stream* pa_stream_new_with_proplist(pa_context* c, const char* name, const pa_sample_spec* ss, const pa_channel_map* map, pa_proplist* proplist);
index 357352a..c06195e 100644 (file)
@@ -259,16 +259,7 @@ bool CreateOutputStream(pa_threaded_mainloop** mainloop,
     // than the default channel map (NULL).
     map = &source_channel_map;
   }
-#if defined(OS_TIZEN)
-  pa_proplist* proplist = pa_proplist_new();
-  pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "browser");
-  *stream = pa_stream_new_with_proplist(*context, "Playback",
-                                        &sample_specifications,
-                                        map, proplist);
-  pa_proplist_free(proplist);
-#else
   *stream = pa_stream_new(*context, "Playback", &sample_specifications, map);
-#endif
   RETURN_ON_FAILURE(*stream, "failed to create PA playback stream");
 
   pa_stream_set_state_callback(*stream, stream_callback, user_data);
diff --git a/src/ozone/patches/0008-Fix-crash-when-switching-to-console-VT-mode.patch b/src/ozone/patches/0008-Fix-crash-when-switching-to-console-VT-mode.patch
new file mode 100644 (file)
index 0000000..803ff93
--- /dev/null
@@ -0,0 +1,30 @@
+From 841609f8245f94194d9e6caabafb4d3878de7051 Mon Sep 17 00:00:00 2001
+From: Joone Hur <joone.hur@intel.com>
+Date: Wed, 1 Oct 2014 15:10:54 -0700
+Subject: [PATCH] Fix crash when switching to console(VT) mode
+
+Buffer swapping should not be synchronized so that the GPU process
+is not blocked by waiting for a frame update from Weston.
+
+Bug: TC-341
+---
+ ui/gl/gl_context_egl.cc |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc
+index 2554f8c..6cd5d4c 100644
+--- a/ui/gl/gl_context_egl.cc
++++ b/ui/gl/gl_context_egl.cc
+@@ -112,6 +112,10 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) {
+     return false;
+   }
+
++#if defined(USE_OZONE)
++  eglSwapInterval(display_, 0);
++#endif
++
+   // Set this as soon as the context is current, since we might call into GL.
+   SetRealGLApi();
+
+--
+1.7.9.5
index 117a872..ad6ba7c 100644 (file)
@@ -457,8 +457,10 @@ void DesktopWindowTreeHostWayland::Minimize() {
 
   state_ |= Minimized;
   previous_bounds_ = bounds_;
+  bounds_ = gfx::Rect();
   ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
                                                               ui::MINIMIZED);
+  OnHostResized(bounds_.size());
 }
 
 void DesktopWindowTreeHostWayland::Restore() {
@@ -791,6 +793,9 @@ void DesktopWindowTreeHostWayland::HandleWindowResize(unsigned width,
 
 void DesktopWindowTreeHostWayland::HandleWindowUnminimized() {
   state_ &= ~Minimized;
+  bounds_ = previous_bounds_;
+  previous_bounds_ = gfx::Rect();
+  OnHostResized(bounds_.size());
 }
 
 void DesktopWindowTreeHostWayland::HandleCommit(const std::string& text) {
index 2554f8c..6cd5d4c 100644 (file)
@@ -112,6 +112,10 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) {
     return false;
   }
 
+#if defined(USE_OZONE)
+  eglSwapInterval(display_, 0);
+#endif
+
   // Set this as soon as the context is current, since we might call into GL.
   SetRealGLApi();
 
index 03685f6..abc193b 100644 (file)
 # Edit these when rolling DEPS.xwalk.
 # -----------------------------------
 
-chromium_crosswalk_rev = '5ee6f9bf16ecbb3d56b195063b9b55d42effb67b'
+chromium_crosswalk_rev = '66c669af8a18cf8d4aa2cc8b798d27e8e1a2feae'
 blink_crosswalk_rev = 'bc7b6c17bc9634579c6df664d04fdf38a1edd56a'
 v8_crosswalk_rev = '452135ceb9d31a6bc30fb39bf743623e0f553afa'
-ozone_wayland_rev = '9595d59e35e37675587523590e21397addf78446'
+ozone_wayland_rev = '113c32025bee544ee34460ce3a29497e69024cee'
 
 crosswalk_git = 'https://github.com/crosswalk-project'
 ozone_wayland_git = 'https://github.com/01org'
index 2c762c0..ee9aaa4 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR=10
 MINOR=38
-BUILD=212
+BUILD=217
 PATCH=0
index 1d06038..245b1b6 100644 (file)
@@ -179,8 +179,9 @@ public abstract class XWalkRuntimeActivityBase extends Activity {
 
     private void showRuntimeLibraryExceptionDialog(String title, String message) {
         if (!mShownNotFoundDialog) {
+            if (SharedXWalkView.isUsingLibrary()) return;
             AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            if (!SharedXWalkView.usesLibraryOutOfPackage()) {
+            if (SharedXWalkView.containsLibrary()) {
                 builder.setPositiveButton(android.R.string.ok,
                         new DialogInterface.OnClickListener() {
                             public void onClick(DialogInterface dialog, int id) {
index 7b661e9..e828997 100755 (executable)
@@ -66,7 +66,7 @@ def ReplaceInvalidChars(value, mode='default'):
     invalid_chars = '\/:.*?"<>|- '
   for c in invalid_chars:
     if mode == 'apkname' and c in value:
-      print("Illegal character: '%s' is replaced with '_'" % c)
+      print('Illegal character: "%s" replaced with "_"' % c)
     value = value.replace(c, '_')
   return value
 
@@ -126,6 +126,10 @@ def Prepare(app_info, compressor):
 
   # 1) copy template project to app_dir
   CleanDir(app_dir)
+  if not os.path.isdir(template_app_dir):
+    print('Error: The template directory could not be found (%s).' %
+          template_app_dir)
+    sys.exit(7)
   shutil.copytree(template_app_dir, app_dir)
 
   # 2) replace app_dir 'src' dir with template 'src' dir
@@ -271,7 +275,7 @@ def ReplaceString(file_path, src, dest):
 
 def SetVariable(file_path, string_line, variable, value):
   function_string = ('%sset%s(%s);\n' %
-                    ('        ', variable, value))
+                     ('        ', variable, value))
   temp_file_path = file_path + '.backup'
   file_handle = open(temp_file_path, 'w+')
   for line in open(file_path):
@@ -335,7 +339,7 @@ def CopyExtensionFile(extension_name, suffix, src_path, dest_path):
   dest_extension_path = os.path.join(dest_path, extension_name)
   if os.path.exists(dest_extension_path):
     # TODO: Refine it by renaming it internally.
-    print('Error: duplicated extension names "%s" are found. Please rename it.'
+    print('Error: duplicate extension names were found (%s). Please rename it.'
           % extension_name)
     sys.exit(9)
   else:
@@ -387,7 +391,7 @@ def CustomizeExtensions(app_info, extensions):
   extension_json_list = []
   for source_path in extension_paths:
     if not os.path.exists(source_path):
-      print('Error: can\'t find the extension directory \'%s\'.' % source_path)
+      print('Error: can not find the extension directory \'%s\'.' % source_path)
       sys.exit(9)
     # Remove redundant separators to avoid empty basename.
     source_path = os.path.normpath(source_path)
@@ -403,7 +407,7 @@ def CustomizeExtensions(app_info, extensions):
     file_name = extension_name + '.json'
     src_file = os.path.join(source_path, file_name)
     if not os.path.isfile(src_file):
-      print('Error: %s is not found in %s.' % (file_name, source_path))
+      print('Error: %s was not found in %s.' % (file_name, source_path))
       sys.exit(9)
     else:
       src_file_handle = open(src_file)
index 19d14e0..b94b6cd 100755 (executable)
@@ -237,19 +237,14 @@ def Customize(options, app_info, manifest):
 
 
 def Execution(options, name):
+  arch_string = (' ('+options.arch+')' if options.arch else '')
+  print('\nStarting application build' + arch_string)
   app_dir = os.path.join(tempfile.gettempdir(), name)
   android_path = Which('android')
-  if android_path is None:
-    print('The "android" binary could not be found. Check your Android SDK '
-          'installation and your PATH environment variable.')
-    sys.exit(1)
-
   api_level = GetAndroidApiLevel(android_path)
-  if api_level < 14:
-    print('Please install Android API level (>=14) first.')
-    sys.exit(3)
   target_string = 'android-%d' % api_level
 
+  print (' * Checking keystore for signing')
   if options.keystore_path:
     key_store = os.path.expanduser(options.keystore_path)
     if options.keystore_alias:
@@ -266,33 +261,31 @@ def Execution(options, name):
     else:
       key_alias_code = None
   else:
-    print ('Use xwalk\'s keystore by default for debugging. '
-           'Please switch to your keystore when distributing it to app market.')
+    print('   No keystore provided for signing. Using xwalk\'s keystore '
+          'for debugging.\n   Please use a valid keystore when '
+          'distributing to the app market.')
     key_store = os.path.join(xwalk_dir, 'xwalk-debug.keystore')
     key_alias = 'xwalkdebugkey'
     key_code = 'xwalkdebug'
     key_alias_code = 'xwalkdebug'
 
-  # Check whether ant is installed.
-  ant_path = Which('ant')
-  if ant_path is None:
-    print('Ant could not be found. Please make sure it is installed.')
-    sys.exit(4)
-
   # Update android project for app and xwalk_core_library.
   update_project_cmd = [android_path, 'update', 'project',
                         '--path', app_dir,
                         '--target', target_string,
                         '--name', name]
   if options.mode == 'embedded':
+    print(' * Updating project with xwalk_core_library')
     RunCommand([android_path, 'update', 'lib-project',
                 '--path', os.path.join(app_dir, 'xwalk_core_library'),
                 '--target', target_string])
     update_project_cmd.extend(['-l', 'xwalk_core_library'])
-
+  else:
+    print(' * Updating project')
   RunCommand(update_project_cmd)
 
   # Check whether external extensions are included.
+  print(' * Checking for external extensions')
   extensions_string = 'xwalk-extensions'
   extensions_dir = os.path.join(app_dir, extensions_string)
   external_extension_jars = FindExtensionJars(extensions_dir)
@@ -302,6 +295,7 @@ def Execution(options, name):
                                  os.path.basename(external_extension_jar)))
 
   if options.mode == 'embedded':
+    print (' * Copying native libraries for %s' % options.arch)
     # Remove existing native libraries in xwalk_core_library, they are probably
     # for the last execution to make apk for another CPU arch.
     # And then copy the native libraries for the specified arch into
@@ -324,22 +318,33 @@ def Execution(options, name):
       sys.exit(10)
 
   if options.project_only:
+    print (' (Skipping apk package creation)')
     return
 
   # Build the APK
+  if options.mode == 'embedded':
+    print(' * Building Android apk package with Crosswalk embedded' +
+          arch_string)
+  else:
+    print(' * Building Android apk package')
+  ant_path = Which('ant')
   ant_cmd = [ant_path, 'release', '-f', os.path.join(app_dir, 'build.xml')]
-  if not options.verbose:
-    ant_cmd.extend(['-quiet'])
   ant_cmd.extend(['-Dkey.store=%s' % os.path.abspath(key_store)])
   ant_cmd.extend(['-Dkey.alias=%s' % key_alias])
   if key_code:
     ant_cmd.extend(['-Dkey.store.password=%s' % key_code])
   if key_alias_code:
     ant_cmd.extend(['-Dkey.alias.password=%s' % key_alias_code])
+
+  cmd_display = ' '.join([str(item) for item in ant_cmd])
+  if options.verbose:
+    print('Executing:\n %s\n' % cmd_display)
+  else:
+    ant_cmd.extend(['-quiet'])
   ant_result = subprocess.call(ant_cmd)
   if ant_result != 0:
     print('Command "%s" exited with non-zero exit code %d'
-          % (' '.join(ant_cmd), ant_result))
+          % (cmd_display, ant_result))
     sys.exit(ant_result)
 
   src_file = os.path.join(app_dir, 'bin', '%s-release.apk' % name)
@@ -352,7 +357,7 @@ def Execution(options, name):
     dst_file = os.path.join(options.target_dir,
                             '%s_%s.apk' % (package_name, options.arch))
   shutil.copyfile(src_file, dst_file)
-
+  print(' (Location: %s)' % dst_file)
 
 def PrintPackageInfo(options, name, packaged_archs):
   package_name_version = os.path.join(options.target_dir, name)
@@ -360,38 +365,55 @@ def PrintPackageInfo(options, name, packaged_archs):
     package_name_version += '_' + options.app_version
 
   if len(packaged_archs) == 0:
-    print ('A non-platform specific APK for the web application "%s" was '
-           'generated successfully at\n%s.apk. It requires a shared Crosswalk '
-           'Runtime to be present.'
+    print ('\nA non-platform specific APK for the web application "%s" was '
+           'generated successfully at:\n %s.apk.\nIt requires a shared '
+           'Crosswalk Runtime to be present.'
            % (name, package_name_version))
     return
 
-  for arch in packaged_archs:
-    print ('An APK for the web application "%s" including the Crosswalk '
-           'Runtime built for %s was generated successfully, which can be '
-           'found at\n%s_%s.apk.'
-           % (name, arch, package_name_version, arch))
-
   all_archs = set(AllArchitectures())
 
   if len(packaged_archs) != len(all_archs):
     missed_archs = all_archs - set(packaged_archs)
-    print ('\n\nWARNING: ')
-    print ('This APK will only work on %s based Android devices. Consider '
-           'building for %s as well.' %
+    print ('\nNote: This APK will only work on %s-based Android devices.'
+           ' Consider building\nfor %s as well.' %
            (', '.join(packaged_archs), ', '.join(missed_archs)))
   else:
-    print ('\n\n%d APKs were created for %s devices. '
-           % (len(all_archs), ', '.join(all_archs)))
-    print ('Please install the one that matches the processor architecture '
-           'of your device.\n\n')
-    print ('If you are going to submit this application to an application '
-           'store, please make sure you submit both packages.\nInstructions '
-           'for submitting multiple APKs to Google Play Store are available '
-           'here:\nhttps://software.intel.com/en-us/html5/articles/submitting'
+    print ("\nApplication apk's were created for %d architectures (%s)." %
+           (len(all_archs), (','.join(all_archs))))
+    print ('If you submit this application to an application '
+           'store, please submit both\npackages. Instructions '
+           'for submitting multiple APKs to Google Play Store are\navailable '
+           'here:')
+    print (' https://software.intel.com/en-us/html5/articles/submitting'
            '-multiple-crosswalk-apk-to-google-play-store')
 
+
+def CheckSystemRequirements():
+  ''' Check for android, ant, template dir '''
+  sys.stdout.write('Checking system requirements...')
+  sys.stdout.flush()
+  # check android install
+  android_path = Which('android')
+  if android_path is None:
+    print('failed\nThe "android" binary could not be found. Check your Android '
+          'SDK installation and your PATH environment variable.')
+    sys.exit(1)
+  if GetAndroidApiLevel(android_path) < 14:
+    print('failed\nPlease install Android API level (>=14) first.')
+    sys.exit(3)
+
+  # Check ant install
+  ant_path = Which('ant')
+  if ant_path is None:
+    print('failed\nAnt could not be found. Please make sure it is installed.')
+    sys.exit(4)
+
+  print('ok')
+
+
 def MakeApk(options, app_info, manifest):
+  CheckSystemRequirements()
   Customize(options, app_info, manifest)
   name = app_info.android_name
   app_dir = os.path.join(tempfile.gettempdir(), name)
@@ -445,15 +467,16 @@ def MakeApk(options, app_info, manifest):
 
   # if project_dir, save build directory
   if options.project_dir:
+    print ('\nCreating project directory')
     save_dir = os.path.join(options.project_dir, name)
     if CreateAndCopyDir(app_dir, save_dir, True):
-      print ('\nA project directory was created successfully in %s' %
-             save_dir)
-      print ('To generate an APK manually, go to %s and run the '
-             'following command:' % save_dir)
-      print ('  ant release -f build.xml')
-      print ('For more information, see\n'
-             ' http://developer.android.com/tools/building/'
+      print ('  A project directory was created successfully in:\n   %s' %
+             os.path.abspath(save_dir))
+      print ('  To manually generate an APK, run the following in that '
+             'directory:')
+      print ('   ant release -f build.xml')
+      print ('  For more information, see:\n'
+             '   http://developer.android.com/tools/building/'
              'building-cmdline.html')
     else:
       print ('Error: Unable to create a project directory during the build. '
@@ -703,4 +726,8 @@ def main(argv):
 
 
 if __name__ == '__main__':
-  sys.exit(main(sys.argv))
+  try:
+    sys.exit(main(sys.argv))
+  except KeyboardInterrupt:
+    print('')
+
index 261a241..08389e4 100755 (executable)
@@ -552,8 +552,8 @@ class TestMakeApk(unittest.TestCase):
     self.checkApks('Example', '1.0.0', keystore_path)
     Clean('Example', '1.0.0')
 
-    keystore_path_with_space = os.path.join(
-      'test_data', 'keystore', 'test keystore')
+    keystore_path_with_space = os.path.join('test_data', 'keystore',
+                                            'test keystore')
     shutil.copy2(keystore_path, keystore_path_with_space)
     keystore_path = os.path.join('test_data', 'keystore',
                                  'xwalk-test.keystore')
@@ -615,8 +615,8 @@ class TestMakeApk(unittest.TestCase):
            '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
     self.addCleanup(Clean, 'Example', '1.0.0')
-    self.assertIn('WARNING: app.launch.local_path is deprecated for Crosswalk',
-                  out)
+    self.assertIn('Warning: The following fields have been deprecated', out)
+    self.assertIn('app.launch.local_path', out)
     Clean('Example', '1.0.0')
 
     manifest_path = os.path.join('test_data', 'manifest', 'deprecated',
@@ -624,7 +624,8 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
            '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
-    self.assertIn('WARNING: launch_path is deprecated for Crosswalk', out)
+    self.assertIn('Warning: The following fields have been deprecated', out)
+    self.assertIn('launch_path', out)
     Clean('Example', '1.0.0')
 
     manifest_path = os.path.join('test_data', 'manifest', 'deprecated',
@@ -632,7 +633,8 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
            '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
-    self.assertIn('WARNING: permissions is deprecated for Crosswalk', out)
+    self.assertIn('Warning: The following fields have been deprecated', out)
+    self.assertIn('permissions', out)
     Clean('Example', '1.0.0')
 
     manifest_path = os.path.join('test_data', 'manifest',
@@ -640,8 +642,8 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
            '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
-    self.assertIn('WARNING: icons defined as dictionary form is deprecated',
-                  out)
+    self.assertIn('Warning: The following fields have been deprecated', out)
+    self.assertIn('icons', out)
     Clean('Example', '1.0.0')
 
     manifest_path = os.path.join('test_data', 'manifest', 'deprecated',
@@ -649,7 +651,8 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
            '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
-    self.assertIn('WARNING: description is deprecated for Crosswalk', out)
+    self.assertIn('Warning: The following fields have been deprecated', out)
+    self.assertIn('description', out)
     Clean('Example', '1.0.0')
 
     manifest_path = os.path.join('test_data', 'manifest', 'deprecated',
@@ -657,7 +660,8 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
            '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
-    self.assertIn('WARNING: version is deprecated for Crosswalk', out)
+    self.assertIn('Warning: The following fields have been deprecated', out)
+    self.assertIn('version', out)
 
   def testManifestWithError(self):
     manifest_path = os.path.join('test_data', 'manifest',
@@ -715,14 +719,12 @@ class TestMakeApk(unittest.TestCase):
     self.checkApks('Example', '1.0.0')
 
   def testExtensionsWithNonExtension(self):
-    # Test with a non-existed extension.
+    # Test with a non-existing extension.
     extension_path = 'test_data/extensions/myextension'
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '--extensions=%s1' % extension_path, self._mode, '--verbose']
     out = RunCommand(cmd)
-    error_msg = 'Error: can\'t find the extension directory'
-    self.assertTrue(out.find(error_msg) != -1)
     self.assertTrue(out.find('Exiting with error code: 9') != -1)
 
   def testExtensionWithPermissions(self):
@@ -936,7 +938,7 @@ class TestMakeApk(unittest.TestCase):
         for img_type in img_types:
           name = orientation + '_' + img_type + '_' + dimension
           path_tmp = os.path.join(launch_screen_path, name)
-          _file = open(path_tmp,'w+')
+          _file = open(path_tmp, 'w+')
           _file.write(name)
           _file.close()
     # Run Test.
@@ -945,8 +947,8 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
            '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
-    self.assertTrue(
-        out.find('WARNING: launch_screen is deprecated for Crosswalk') != -1)
+    self.assertIn('Warning: The following fields have been deprecated', out)
+    self.assertTrue(out.find('launch_screen') != -1)
     Clean('Example', '1.0.0')
     manifest_path = os.path.join('test_data', 'launchScreen', 'manifest.json')
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
index 889b516..4da994a 100755 (executable)
@@ -58,9 +58,13 @@ def ParseLaunchScreen(ret_dict, launch_screen_dict, orientation):
           sub_dict['image_border'])
 
 
-def PrintDeprecationWarning(item):
-  print ('WARNING: %s is deprecated for Crosswalk. Please follow '
-         'https://www.crosswalk-project.org/#documentation/manifest.' % item)
+def PrintDeprecationWarning(deprecated_items):
+  if len(deprecated_items) > 0:
+    print ('  Warning: The following fields have been deprecated for '
+           'Crosswalk:\n   %s' %
+           ', '.join([str(item) for item in deprecated_items]))
+    print ('  Please follow: https://www.crosswalk-project.org/#documentation/'
+           'manifest.')
 
 
 class ManifestJsonParser(object):
@@ -108,7 +112,9 @@ class ManifestJsonParser(object):
     fullscreen:       The fullscreen flag of the application.
     launch_screen:    The launch screen configuration.
     """
+    print ("Checking manifest file")
     ret_dict = {}
+    deprecated_items = []
     if 'name' not in self.data_src:
       print('Error: no \'name\' field in manifest.json file.')
       sys.exit(1)
@@ -121,17 +127,17 @@ class ManifestJsonParser(object):
     elif 'xwalk_version' in self.data_src:
       ret_dict['version'] = self.data_src['xwalk_version']
     elif 'version' in self.data_src:
-      PrintDeprecationWarning('version')
+      deprecated_items.append('version')
       ret_dict['version'] = self.data_src['version']
     if 'start_url' in self.data_src:
       app_url = self.data_src['start_url']
     elif 'launch_path' in self.data_src:
-      PrintDeprecationWarning('launch_path')
+      deprecated_items.append('launch_path')
       app_url = self.data_src['launch_path']
     elif ('app' in self.data_src and
           'launch' in self.data_src['app'] and
           'local_path' in self.data_src['app']['launch']):
-      PrintDeprecationWarning('app.launch.local_path')
+      deprecated_items.append('app.launch.local_path')
       app_url = self.data_src['app']['launch']['local_path']
     else:
       app_url = ''
@@ -144,7 +150,7 @@ class ManifestJsonParser(object):
     if 'icons' in self.data_src:
       icons = self.data_src['icons']
       if type(icons) == dict:
-        PrintDeprecationWarning('icons defined as dictionary form')
+        deprecated_items.append('icons defined as index:value')
         ret_dict['icons'] = icons
       elif type(icons) == list:
         icons_dict = {}
@@ -165,7 +171,7 @@ class ManifestJsonParser(object):
     elif 'xwalk_description' in self.data_src:
       ret_dict['description'] = self.data_src['xwalk_description']
     elif 'description' in self.data_src:
-      PrintDeprecationWarning('description')
+      deprecated_items.append('description')
       ret_dict['description'] = self.data_src['description']
     ret_dict['app_url'] = app_url
     ret_dict['app_root'] = app_root
@@ -179,7 +185,7 @@ class ManifestJsonParser(object):
         print('\'Permissions\' field error in manifest.json file.')
         sys.exit(1)
     elif 'permissions' in self.data_src:
-      PrintDeprecationWarning('permissions')
+      deprecated_items.append('permissions')
       try:
         permission_list = self.data_src['permissions']
         ret_dict['permissions'] = HandlePermissionList(permission_list)
@@ -211,11 +217,13 @@ class ManifestJsonParser(object):
       ParseLaunchScreen(ret_dict, launch_screen_dict, 'portrait')
       ParseLaunchScreen(ret_dict, launch_screen_dict, 'landscape')
     elif 'launch_screen' in self.data_src:
-      PrintDeprecationWarning('launch_screen')
+      deprecated_items.append('launch_screen')
       launch_screen_dict = self.data_src['launch_screen']
       ParseLaunchScreen(ret_dict, launch_screen_dict, 'default')
       ParseLaunchScreen(ret_dict, launch_screen_dict, 'portrait')
       ParseLaunchScreen(ret_dict, launch_screen_dict, 'landscape')
+
+    PrintDeprecationWarning(deprecated_items)
     return ret_dict
 
   def ShowItems(self):
@@ -232,29 +240,29 @@ class ManifestJsonParser(object):
     print("orientation: %s" % self.GetOrientation())
     print("fullscreen: %s" % self.GetFullScreenFlag())
     print('launch_screen.default.background_color: %s' %
-        self.GetLaunchScreenBackgroundColor('default'))
+          self.GetLaunchScreenBackgroundColor('default'))
     print('launch_screen.default.background_image: %s' %
-        self.GetLaunchScreenBackgroundImage('default'))
+          self.GetLaunchScreenBackgroundImage('default'))
     print('launch_screen.default.image: %s' %
-        self.GetLaunchScreenImage('default'))
+          self.GetLaunchScreenImage('default'))
     print('launch_screen.default.image_border: %s' %
-        self.GetLaunchScreenImageBorder('default'))
+          self.GetLaunchScreenImageBorder('default'))
     print('launch_screen.portrait.background_color: %s' %
-        self.GetLaunchScreenBackgroundColor('portrait'))
+          self.GetLaunchScreenBackgroundColor('portrait'))
     print('launch_screen.portrait.background_image: %s' %
-        self.GetLaunchScreenBackgroundImage('portrait'))
+          self.GetLaunchScreenBackgroundImage('portrait'))
     print('launch_screen.portrait.image: %s' %
-        self.GetLaunchScreenImage('portrait'))
+          self.GetLaunchScreenImage('portrait'))
     print('launch_screen.portrait.image_border: %s' %
-        self.GetLaunchScreenImageBorder('portrait'))
+          self.GetLaunchScreenImageBorder('portrait'))
     print('launch_screen.landscape.background_color: %s' %
-        self.GetLaunchScreenBackgroundColor('landscape'))
+          self.GetLaunchScreenBackgroundColor('landscape'))
     print('launch_screen.landscape.background_image: %s' %
-        self.GetLaunchScreenBackgroundImage('landscape'))
+          self.GetLaunchScreenBackgroundImage('landscape'))
     print('launch_screen.landscape.image: %s' %
-        self.GetLaunchScreenImage('landscape'))
+          self.GetLaunchScreenImage('landscape'))
     print('launch_screen.landscape.image_border: %s' %
-        self.GetLaunchScreenImageBorder('landscape'))
+          self.GetLaunchScreenImageBorder('landscape'))
 
   def GetAppName(self):
     """Return the application name."""
index cc8b7c5..0f2ba0b 100644 (file)
@@ -123,6 +123,14 @@ void ApplicationTizen::Hide() {
   }
 }
 
+void ApplicationTizen::Show() {
+  DCHECK(!runtimes_.empty());
+  for (Runtime* runtime : runtimes_) {
+    if (auto window = runtime->window())
+      window->Restore();
+  }
+}
+
 bool ApplicationTizen::Launch(const LaunchParams& launch_params) {
   if (Application::Launch(launch_params)) {
     DCHECK(web_contents_);
index 64767c3..6302ad8 100644 (file)
@@ -27,6 +27,7 @@ class ApplicationTizen :  // NOLINT
  public:
   virtual ~ApplicationTizen();
   void Hide();
+  void Show();
   void Suspend();
   void Resume();
 
index 2437f48..87877dc 100644 (file)
@@ -269,6 +269,7 @@ void RunningApplicationObject::OnResume(
   }
 
   ToApplicationTizen(application_)->Resume();
+  ToApplicationTizen(application_)->Show();
 
   scoped_ptr<dbus::Response> response =
       dbus::Response::FromMethodCall(method_call);
index 3736a56..693ccf2 100644 (file)
@@ -20,7 +20,7 @@
 namespace {
 
 ail_cb_ret_e appinfo_get_app_id_cb(
-    const ail_appinfo_h appinfo, void* user_data) {
+    const ail_appinfo_h appinfo, void* user_data, uid_t /*uid*/) {
   std::vector<std::string>* app_ids =
     static_cast<std::vector<std::string>*>(user_data);
   char* app_id;
index 1165554..0ad9df2 100644 (file)
 
 namespace {
 
-typedef ail_cb_ret_e (*PropertyCallback)(const ail_appinfo_h, void*);
+typedef ail_cb_ret_e (*PropertyCallback)(const ail_appinfo_h, void*, uid_t);
 
 ail_cb_ret_e callback_x_slp_exe_path(const ail_appinfo_h appinfo,
-    void* user_data) {
+    void* user_data, uid_t /*uid*/) {
   char* package_exec;
   ail_appinfo_get_str(appinfo, AIL_PROP_X_SLP_EXE_PATH, &package_exec);
   if (!package_exec)
@@ -28,7 +28,7 @@ ail_cb_ret_e callback_x_slp_exe_path(const ail_appinfo_h appinfo,
 }
 
 ail_cb_ret_e callback_installed_time(const ail_appinfo_h appinfo,
-    void* user_data) {
+    void* user_data, uid_t /*uid*/) {
   int* installed_time = static_cast<int*>(user_data);
   ail_appinfo_get_int(appinfo, AIL_PROP_X_SLP_INSTALLEDTIME_INT,
       installed_time);
index 967ea4f..f3079d9 100644 (file)
@@ -6,6 +6,12 @@
 
 #include <assert.h>
 #include <pkgmgr/pkgmgr_parser.h>
+
+#include <pkgmgr_installer.h>
+// logging and dlog uses same macro name
+// to avoid warnings we need to undefine dlog's one
+#undef LOG
+
 #include <tzplatform_config.h>
 
 #include <string>
index 5867ce2..31e175a 100644 (file)
@@ -5,12 +5,12 @@
 #ifndef XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PLATFORM_INSTALLER_H_
 #define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PLATFORM_INSTALLER_H_
 
-#include <pkgmgr_installer.h>
-
 #include <string>
 
 #include "base/files/file_path.h"
 
+struct pkgmgr_installer;
+
 class PlatformInstaller {
  public:
   PlatformInstaller();
index b8c576a..88d9c84 100644 (file)
@@ -16,7 +16,7 @@
 %endif
 
 Name:           crosswalk
-Version:        10.38.212.0
+Version:        10.38.217.0
 Release:        0
 Summary:        Chromium-based app runtime
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -140,6 +140,13 @@ cp -a src/xwalk/LICENSE LICENSE.xwalk
 
 %build
 
+# Stop unconditionally passing -Wall to the compiler. Chromium has its own
+# mechanisms for deciding which parts of the code need -Wall and which need it
+# to be left out (since several pieces are built with -Werror). At least in
+# M39, this is preventing the "rtc_base" target from being built because it
+# does not expect -Wall to be passed to the compiler (see webrtc issue 3307).
+export CXXFLAGS=`echo $CXXFLAGS | sed s,-Wall,,g`
+
 # For ffmpeg on ia32. The original CFLAGS set by the gyp and config files in
 # src/third_party/ffmpeg already pass -O2 -fomit-frame-pointer, but Tizen's
 # CFLAGS end up appending -fno-omit-frame-pointer. See http://crbug.com/37246
index 2b83866..e63d754 100644 (file)
@@ -39,7 +39,11 @@ public class SharedXWalkView extends XWalkView {
         initialized = true;
     }
 
-    public static boolean usesLibraryOutOfPackage() {
-        return ReflectionHelper.shouldUseLibrary();
+    public static boolean containsLibrary() {
+        return !ReflectionHelper.shouldUseLibrary();
+    }
+
+    public static boolean isUsingLibrary() {
+        return ReflectionHelper.isUsingLibrary();
     }
 }
index 883a448..4aa5cfe 100644 (file)
@@ -73,24 +73,49 @@ public class ReflectionHelper {
     private final static String LIBRARY_APK_PACKAGE = "org.xwalk.core";
     /* Wrapper Only
     private static boolean sAllowCrossPackage = false;
+    private static boolean sAlreadyUsingLibrary = false;
     private static SharedXWalkExceptionHandler sExceptionHandler = null;
 
     static void setExceptionHandler(SharedXWalkExceptionHandler handler) {
         sExceptionHandler = handler;
     }
 
-    public static boolean shouldUseLibrary() {
+    static boolean isUsingLibrary() {
+        return sAlreadyUsingLibrary;
+    }
+
+    static boolean shouldUseLibrary() {
+        if (sAlreadyUsingLibrary) return true;
+
         // TODO(wang16): There are many other conditions here.
         // e.g. Whether application uses the ApplicationClass we provided,
         //      Whether native library arch is correct.
         assert isWrapper();
+        Class<?> delegateClass = null;
         try {
-            ReflectionHelper.class.getClassLoader().loadClass(
-                    INTERNAL_PACKAGE + "." + "ReflectionHelper");
-            return false;
+            ClassLoader classLoader = ReflectionHelper.class.getClassLoader();
+            delegateClass = classLoader.loadClass(
+                    INTERNAL_PACKAGE + "." + "XWalkViewDelegate");
         } catch (ClassNotFoundException e) {
             return true;
         }
+        if (delegateClass == null) return true;
+        try {
+            Method loadXWalkLibrary = delegateClass.getDeclaredMethod(
+                    "loadXWalkLibrary", Context.class);
+            loadXWalkLibrary.invoke(null, (Context)null);
+        } catch (NoSuchMethodException e) {
+            return true;
+        } catch (IllegalArgumentException e) {
+            return true;
+        } catch (IllegalAccessException e) {
+            return true;
+        } catch (InvocationTargetException e) {
+            return true;
+        } catch (UnsatisfiedLinkError e) {
+            return true;
+        }
+        return false;
     }
     Wrapper Only */
 
@@ -121,6 +146,7 @@ public class ReflectionHelper {
                 sBridgeContext = app.createPackageContext(
                         LIBRARY_APK_PACKAGE,
                         Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+                sAlreadyUsingLibrary = true;
             } catch (PackageManager.NameNotFoundException e) {
                 handleException(e);
             }
index b00d31f..0755f6f 100644 (file)
@@ -41,6 +41,7 @@ class XWalkContentsClientBridge extends XWalkContentsClient
         implements ContentViewDownloadDelegate {
     private static final String TAG = XWalkContentsClientBridge.class.getName();
     private static final int NEW_XWALKVIEW_CREATED = 100;
+    private static final int NEW_ICON_DOWNLOAD     = 101;
 
     private XWalkViewInternal mXWalkView;
     private XWalkUIClientInternal mXWalkUIClient;
@@ -110,6 +111,10 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
                         mXWalkView.completeWindowCreation(newXWalkView);
                         break;
+                    case NEW_ICON_DOWNLOAD:
+                        String url = (String) msg.obj;
+                        nativeDownloadIcon(mNativeContentsClientBridge, url);
+                        break;
                     default:
                         throw new IllegalStateException();
                 }
@@ -711,6 +716,17 @@ class XWalkContentsClientBridge extends XWalkContentsClient
         onScaleChanged(oldPageScaleFactor, mPageScaleFactor);
     }
 
+    @CalledByNative
+    public void onIconAvailable(String url) {
+        Message m = mUiThreadHandler.obtainMessage(NEW_ICON_DOWNLOAD, url);
+        mXWalkUIClient.onIconAvailable(mXWalkView, url, m);
+    }
+
+    @CalledByNative
+    public void onReceivedIcon(String url, Bitmap icon) {
+        mXWalkUIClient.onReceivedIcon(mXWalkView, url, icon);
+    }
+
     //--------------------------------------------------------------------------------------------
     //  Native methods
     //--------------------------------------------------------------------------------------------
@@ -729,4 +745,5 @@ class XWalkContentsClientBridge extends XWalkContentsClient
             int processId, int renderId, int mode_flags, String filepath, String displayName);
     private native void nativeOnFilesNotSelected(long nativeXWalkContentsClientBridge,
             int processId, int renderId, int mode_flags);
+    private native void nativeDownloadIcon(long nativeXWalkContentsClientBridge, String url);
 }
index 72ee258..f184189 100644 (file)
@@ -8,9 +8,11 @@ import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
+import android.os.Message;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.WindowManager;
@@ -78,8 +80,8 @@ public class XWalkUIClientInternal {
 
     /**
      * Request the host application to create a new window
-     * @param view The XWalkView from which the request for a new window originated
-     * @param initiator The request was initiated by a user gesture of javascript
+     * @param view The XWalkView which initiate the request for a new window
+     * @param initiator How the request was initiated
      * @param callback Callback when once a new XWalkView has been created
      * @return Return true if the host application will create a new window
      * @since 4.0
@@ -91,6 +93,28 @@ public class XWalkUIClientInternal {
     }
 
     /**
+     * Notify the host application that an icon is available, send the message to start the downloading
+     * @param view The XWalkView that icon belongs to
+     * @param url The icon url
+     * @param startDownload Message to initiate icon download
+     * @since 4.0
+     */
+    @XWalkAPI
+    public void onIconAvailable(XWalkViewInternal view, String url, Message startDownload) {
+    }
+
+    /**
+     * Notify the host application of a new icon has been downloaded
+     * @param view The XWalkView that icon belongs to
+     * @param url The icon url
+     * @param icon The icon image
+     * @since 4.0
+     */
+    @XWalkAPI
+    public void onReceivedIcon(XWalkViewInternal view, String url, Bitmap icon) {
+    }
+
+    /**
      * Request display and focus for this XWalkViewInternal.
      * @param view the owner XWalkViewInternal instance.
      * @since 1.0
index 238c43e..d61c82d 100644 (file)
@@ -4,6 +4,7 @@
 
 package org.xwalk.core.internal;
 
+import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.IOException;
@@ -33,6 +34,7 @@ import org.chromium.net.NetworkChangeNotifier;
 @JNINamespace("xwalk")
 class XWalkViewDelegate {
     private static boolean sInitialized = false;
+    private static boolean sLibraryLoaded = false;
     private static boolean sRunningOnIA = true;
     private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "xwalkcore";
     private static final String[] MANDATORY_PAKS = {
@@ -77,11 +79,38 @@ class XWalkViewDelegate {
         }
     }
 
+    public static void loadXWalkLibrary(Context context) throws UnsatisfiedLinkError {
+        if (sLibraryLoaded) return;
+
+        // If context is null, it's called from wrapper's ReflectionHelper to try
+        // loading native library within the package. No need to try load from library
+        // package in this case.
+        // If context's applicationContext is not the same package with itself,
+        // It's a cross package invoking, load core library from library apk.
+        // Only load the native library from /data/data if the Android version is
+        // lower than 4.2. Android enables a system path /data/app-lib to store native
+        // libraries starting from 4.2 and load them automatically.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 && context != null &&
+                !context.getApplicationContext().getPackageName().equals(context.getPackageName())) {
+            for (String library : MANDATORY_LIBRARIES) {
+                System.load("/data/data/" + context.getPackageName() + "/lib/" + library);
+            }
+        }
+        loadLibrary(context);
+
+        if (sRunningOnIA && !nativeIsLibraryBuiltForIA()) {
+            throw new UnsatisfiedLinkError();
+        }
+        sLibraryLoaded = true;
+    }
+
     public static void init(XWalkViewInternal xwalkView) throws UnsatisfiedLinkError {
         if (sInitialized) {
             return;
         }
 
+        loadXWalkLibrary(xwalkView.getContext());
+
         // Initialize the ActivityStatus. This is needed and used by many internal
         // features such as location provider to listen to activity status.
         ApplicationStatusManager.init(xwalkView.getActivity().getApplication());
@@ -105,23 +134,6 @@ class XWalkViewDelegate {
             CommandLine.init(readCommandLine(context.getApplicationContext()));
         }
 
-        // If context's applicationContext is not the same package with itself,
-        // It's a cross package invoking, load core library from library apk.
-        // Only load the native library from /data/data if the Android version is
-        // lower than 4.2. Android enables a system path /data/app-lib to store native
-        // libraries starting from 4.2 and load them automatically.
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 &&
-                !context.getApplicationContext().getPackageName().equals(context.getPackageName())) {
-            for (String library : MANDATORY_LIBRARIES) {
-                System.load("/data/data/" + context.getPackageName() + "/lib/" + library);
-            }
-        }
-        loadLibrary(context);
-
-        if (sRunningOnIA && !nativeIsLibraryBuiltForIA()) {
-            throw new UnsatisfiedLinkError();
-        }
-
         ResourceExtractor.setMandatoryPaksToExtract(MANDATORY_PAKS);
         final int resourcesListResId = context.getResources().getIdentifier(
                 XWALK_RESOURCES_LIST_RES_NAME, "array", context.getPackageName());
@@ -232,5 +244,21 @@ class XWalkViewDelegate {
 
     static {
         sRunningOnIA = Build.CPU_ABI.equalsIgnoreCase("x86");
+        if (!sRunningOnIA) {
+            // This is not the final decision yet.
+            // With latest Houdini, an app with ARM binary will see system abi as if it's running on
+            // arm device. Here needs some further check for real system abi.
+            try {
+                Process process = Runtime.getRuntime().exec("getprop ro.product.cpu.abi");
+                InputStreamReader ir = new InputStreamReader(process.getInputStream());
+                BufferedReader input = new BufferedReader(ir);
+                String abi = input.readLine();
+                sRunningOnIA = abi.contains("x86");
+                input.close();
+                ir.close();
+            } catch (IOException e) {
+                Log.w(TAG, Log.getStackTraceString(e));
+            }
+        }
     }
 }
index 4450014..a7fb148 100644 (file)
@@ -142,10 +142,10 @@ void XWalkContent::SetJavaPeers(JNIEnv* env,
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   java_ref_ = JavaObjectWeakGlobalRef(env, xwalk_content);
 
-  web_contents_delegate_.reset(
-      new XWalkWebContentsDelegate(env, web_contents_delegate));
-  contents_client_bridge_.reset(
-      new XWalkContentsClientBridge(env, contents_client_bridge));
+  web_contents_delegate_.reset(new XWalkWebContentsDelegate(
+      env, web_contents_delegate));
+  contents_client_bridge_.reset(new XWalkContentsClientBridge(
+      env, contents_client_bridge, web_contents_.get()));
 
   web_contents_->SetUserData(
       kXWalkContentUserDataKey, new XWalkContentUserData(this));
index 992db8b..d5b30af 100644 (file)
@@ -60,11 +60,15 @@ ScopedPtrHashMap<int, content::DesktopNotificationDelegate> g_notification_map_;
 }  // namespace
 
 
-XWalkContentsClientBridge::XWalkContentsClientBridge(JNIEnv* env, jobject obj)
-    : java_ref_(env, obj) {
+XWalkContentsClientBridge::XWalkContentsClientBridge(
+    JNIEnv* env, jobject obj,
+    content::WebContents* web_contents)
+    : java_ref_(env, obj),
+      icon_helper_(new XWalkIconHelper(web_contents)) {
   DCHECK(obj);
   Java_XWalkContentsClientBridge_setNativeContentsClientBridge(
       env, obj, reinterpret_cast<intptr_t>(this));
+  icon_helper_->SetListener(this);
 }
 
 XWalkContentsClientBridge::~XWalkContentsClientBridge() {
@@ -433,6 +437,38 @@ void XWalkContentsClientBridge::OnFilesNotSelected(
       files, static_cast<content::FileChooserParams::Mode>(mode));
 }
 
+void XWalkContentsClientBridge::DownloadIcon(JNIEnv* env,
+                                             jobject obj,
+                                             jstring url) {
+  std::string url_str = base::android::ConvertJavaStringToUTF8(env, url);
+  icon_helper_->DownloadIcon(GURL(url_str));
+}
+
+void XWalkContentsClientBridge::OnIconAvailable(const GURL& icon_url) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+
+  ScopedJavaLocalRef<jstring> jurl(
+      ConvertUTF8ToJavaString(env, icon_url.spec()));
+
+  Java_XWalkContentsClientBridge_onIconAvailable(env, obj.obj(), jurl.obj());
+}
+
+void XWalkContentsClientBridge::OnReceivedIcon(const GURL& icon_url,
+                                               const SkBitmap& bitmap) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+
+  ScopedJavaLocalRef<jstring> jurl(
+      ConvertUTF8ToJavaString(env, icon_url.spec()));
+  ScopedJavaLocalRef<jobject> jicon = gfx::ConvertToJavaBitmap(&bitmap);
+
+  Java_XWalkContentsClientBridge_onReceivedIcon(
+      env, obj.obj(), jurl.obj(), jicon.obj());
+}
+
 bool RegisterXWalkContentsClientBridge(JNIEnv* env) {
   return RegisterNativesImpl(env) >= 0;
 }
index a1e6ed9..18ee50b 100644 (file)
@@ -17,6 +17,7 @@
 #include "base/id_map.h"
 #include "content/public/browser/javascript_dialog_manager.h"
 #include "xwalk/runtime/browser/android/xwalk_contents_client_bridge_base.h"
+#include "xwalk/runtime/browser/android/xwalk_icon_helper.h"
 
 namespace gfx {
 class Size;
@@ -26,6 +27,10 @@ namespace net {
 class X509Certificate;
 }
 
+namespace content {
+class WebContents;
+}
+
 class SkBitmap;
 
 namespace xwalk {
@@ -37,9 +42,11 @@ namespace xwalk {
 // indirect refs from the Application (via callbacks) and so can outlive
 // XWalkView, this class notifies it before being destroyed and to nullify
 // any references.
-class XWalkContentsClientBridge : public XWalkContentsClientBridgeBase {
+class XWalkContentsClientBridge : public XWalkContentsClientBridgeBase ,
+                                  public XWalkIconHelper::Listener {
  public:
-  XWalkContentsClientBridge(JNIEnv* env, jobject obj);
+  XWalkContentsClientBridge(JNIEnv* env, jobject obj,
+                            content::WebContents* web_contents);
   virtual ~XWalkContentsClientBridge();
 
   // XWalkContentsClientBridgeBase implementation
@@ -100,6 +107,11 @@ class XWalkContentsClientBridge : public XWalkContentsClientBridgeBase {
       int mode, jstring filepath, jstring display_name);
   void OnFilesNotSelected(
       JNIEnv*, jobject, int process_id, int render_id, int mode);
+  void DownloadIcon(JNIEnv* env, jobject obj, jstring url);
+
+  // XWalkIconHelper::Listener Interface
+  virtual void OnIconAvailable(const GURL& icon_url);
+  virtual void OnReceivedIcon(const GURL& icon_url, const SkBitmap& bitmap);
 
  private:
   JavaObjectWeakGlobalRef java_ref_;
@@ -114,6 +126,8 @@ class XWalkContentsClientBridge : public XWalkContentsClientBridgeBase {
   typedef std::map<int, NotificationDownloadRequestInfos >
     NotificationDownloadRequestIdMap;
   NotificationDownloadRequestIdMap downloading_icon_notifications_;
+
+  scoped_ptr<XWalkIconHelper> icon_helper_;
 };
 
 bool RegisterXWalkContentsClientBridge(JNIEnv* env);
diff --git a/src/xwalk/runtime/browser/android/xwalk_icon_helper.cc b/src/xwalk/runtime/browser/android/xwalk_icon_helper.cc
new file mode 100644 (file)
index 0000000..804f043
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/browser/android/xwalk_icon_helper.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/favicon_url.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/size.h"
+
+using content::BrowserThread;
+using content::WebContents;
+
+namespace xwalk {
+
+XWalkIconHelper::XWalkIconHelper(WebContents* web_contents)
+    : content::WebContentsObserver(web_contents),
+      listener_(NULL) {
+}
+
+XWalkIconHelper::~XWalkIconHelper() {
+}
+
+void XWalkIconHelper::SetListener(Listener* listener) {
+  listener_ = listener;
+}
+
+void XWalkIconHelper::DownloadIcon(const GURL& icon_url) {
+  web_contents()->DownloadImage(icon_url, true, 0,
+      base::Bind(&XWalkIconHelper::DownloadFaviconCallback,
+                 base::Unretained(this)));
+}
+
+void XWalkIconHelper::DidUpdateFaviconURL(
+    const std::vector<content::FaviconURL>& candidates) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  for (std::vector<content::FaviconURL>::const_iterator i = candidates.begin();
+       i != candidates.end(); ++i) {
+    if (!i->icon_url.is_valid())
+      continue;
+
+    switch (i->icon_type) {
+      case content::FaviconURL::FAVICON:
+        if (listener_) listener_->OnIconAvailable(i->icon_url);
+        break;
+      case content::FaviconURL::TOUCH_ICON:
+        break;
+      case content::FaviconURL::TOUCH_PRECOMPOSED_ICON:
+        break;
+      case content::FaviconURL::INVALID_ICON:
+        break;
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+}
+
+void XWalkIconHelper::DownloadFaviconCallback(
+    int id,
+    int http_status_code,
+    const GURL& image_url,
+    const std::vector<SkBitmap>& bitmaps,
+    const std::vector<gfx::Size>& original_bitmap_sizes) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (http_status_code == 404 || bitmaps.size() == 0) return;
+
+  if (listener_) listener_->OnReceivedIcon(image_url, bitmaps[0]);
+}
+
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/android/xwalk_icon_helper.h b/src/xwalk/runtime/browser/android/xwalk_icon_helper.h
new file mode 100644 (file)
index 0000000..0bff471
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_BROWSER_ANDROID_XWALK_ICON_HELPER_H_
+#define XWALK_RUNTIME_BROWSER_ANDROID_XWALK_ICON_HELPER_H_
+
+#include <string>
+#include <vector>
+#include "content/public/browser/web_contents_observer.h"
+#include "url/gurl.h"
+
+class SkBitmap;
+
+namespace content {
+struct FaviconURL;
+class WebContents;
+}
+
+namespace gfx {
+class Size;
+}
+
+namespace xwalk {
+
+class XWalkIconHelper : public content::WebContentsObserver {
+ public:
+  class Listener {
+   public:
+    virtual void OnIconAvailable(const GURL& icon_url) = 0;
+    virtual void OnReceivedIcon(const GURL& icon_url,
+                                const SkBitmap& bitmap) = 0;
+   protected:
+    virtual ~Listener() {}
+  };
+
+  explicit XWalkIconHelper(content::WebContents* web_contents);
+  virtual ~XWalkIconHelper();
+
+  void SetListener(Listener* listener);
+
+  void DownloadIcon(const GURL& icon_url);
+
+  // From WebContentsObserver
+  virtual void DidUpdateFaviconURL(
+      const std::vector<content::FaviconURL>& candidates) OVERRIDE;
+
+  void DownloadFaviconCallback(
+      int id,
+      int http_status_code,
+      const GURL& image_url,
+      const std::vector<SkBitmap>& bitmaps,
+      const std::vector<gfx::Size>& original_bitmap_sizes);
+
+ private:
+  Listener* listener_;
+
+  DISALLOW_COPY_AND_ASSIGN(XWalkIconHelper);
+};
+
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_BROWSER_ANDROID_XWALK_ICON_HELPER_H_
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnFullscreenToggledTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnFullscreenToggledTest.java
new file mode 100644 (file)
index 0000000..4754def
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2014 Intel Corporation. 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.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Test suite for OnFullscreenToggled().
+ */
+public class OnFullscreenToggledTest extends XWalkViewTestBase {
+    private TestHelperBridge.OnFullscreenToggledHelper mOnFullscreenToggledHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mOnFullscreenToggledHelper = mTestHelperBridge.getOnFullscreenToggledHelper();
+    }
+
+    @SmallTest
+    @Feature({"OnFullscreenToggled"})
+    public void testOnFullscreenToggled() throws Throwable {
+        final String name = "fullscreen_togged.html";
+        String fileContent = getFileContent(name);
+        int count = mOnFullscreenToggledHelper.getCallCount();
+
+        loadDataSync(null, fileContent, "text/html", false);
+        clickOnElementId("fullscreen_toggled", null);
+        mOnFullscreenToggledHelper.waitForCallback(count);
+        assertTrue(mOnFullscreenToggledHelper.getEnterFullscreen());
+    }
+}
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnJavascriptModalDialogTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnJavascriptModalDialogTest.java
new file mode 100644 (file)
index 0000000..d14b983
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2014 Intel Corporation. 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.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Test suite for OnJavascriptModalDialog().
+ */
+public class OnJavascriptModalDialogTest extends XWalkViewTestBase {
+    private TestHelperBridge.OnJavascriptModalDialogHelper mOnJavascriptModalDialogHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mOnJavascriptModalDialogHelper = mTestHelperBridge.getOnJavascriptModalDialogHelper();
+    }
+
+    @SmallTest
+    @Feature({"OnJavascriptModalDialog"})
+    public void testOnJavascriptModalDialog() throws Throwable {
+        final String url = "js_modal_dialog.html";
+        String fileContent = getFileContent(url);
+        int count = mOnJavascriptModalDialogHelper.getCallCount();
+
+        loadDataSync(null, fileContent, "text/html", false);
+        clickOnElementId("js_modal_dialog", null);
+        mOnJavascriptModalDialogHelper.waitForCallback(count);
+        assertEquals("hello", mOnJavascriptModalDialogHelper.getMessage());
+    }
+}
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnPageLoadStartedTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnPageLoadStartedTest.java
new file mode 100644 (file)
index 0000000..f80cfc2
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (c) 2014 Intel Corporation. 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.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.MediumTest;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
+import org.chromium.net.test.util.TestWebServer;
+
+/**
+ * Tests for the XWalkUIClient.onPageLoadStarted() method.
+ */
+public class OnPageLoadStartedTest extends XWalkViewTestBase {
+    TestCallbackHelperContainer.OnPageStartedHelper mOnPageStartedHelper;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        mOnPageStartedHelper = mTestHelperBridge.getOnPageStartedHelper();
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStarted"})
+    public void testOnPageLoadStartedWithLocalUrl() throws Throwable {
+        String url = "file:///android_asset/www/index.html";
+        int currentCallCount = mOnPageStartedHelper.getCallCount();
+        loadUrlAsync(url);
+
+        mOnPageStartedHelper.waitForCallback(currentCallCount);
+        assertEquals(url, mOnPageStartedHelper.getUrl());
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStarted"})
+    public void testOnPageLoadStartedWithServer() throws Throwable {
+        TestWebServer webServer = null;
+        try {
+            webServer = new TestWebServer(false);
+            final String testHtml = "<html><head>Header</head><body>Body</body></html>";
+            final String testPath = "/test.html";
+
+            final String testUrl = webServer.setResponse(testPath, testHtml, null);
+            int currentCallCount = mOnPageStartedHelper.getCallCount();
+            loadUrlAsync(testUrl);
+
+            mOnPageStartedHelper.waitForCallback(currentCallCount);
+            assertEquals(testUrl, mOnPageStartedHelper.getUrl());
+        } finally {
+            if (webServer != null) webServer.shutdown();
+        }
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStarted"})
+    public void testOnPageLoadStartedWithInvalidUrl() throws Throwable {
+        String url = "http://this.url.is.invalid/";
+        int currentCallCount = mOnPageStartedHelper.getCallCount();
+        loadUrlAsync(url);
+
+        mOnPageStartedHelper.waitForCallback(currentCallCount);
+        assertEquals(url, mOnPageStartedHelper.getUrl());
+    }
+}
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnPageLoadStoppedTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnPageLoadStoppedTest.java
new file mode 100644 (file)
index 0000000..9602b56
--- /dev/null
@@ -0,0 +1,119 @@
+// Copyright (c) 2014 Intel Corporation. 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.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.util.concurrent.TimeUnit;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
+import org.chromium.net.test.util.TestWebServer;
+
+import org.xwalk.core.XWalkUIClient.LoadStatus;
+
+import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
+
+/**
+ * Tests for the XWalkUIClient.onPageLoadStopped() method.
+ */
+public class OnPageLoadStoppedTest extends XWalkViewTestBase {
+    private static final long WAIT_TIMEOUT_MS = scaleTimeout(2000);
+    TestWebServer mWebServer = null;
+    TestCallbackHelperContainer.OnPageFinishedHelper mOnPageFinishedHelper;
+    TestCallbackHelperContainer.OnReceivedErrorHelper mOnReceivedErrorHelper;
+    TestCallbackHelperContainer.OnPageStartedHelper mOnPageStartedHelper;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        mWebServer = new TestWebServer(false);
+        mOnPageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
+        mOnReceivedErrorHelper = mTestHelperBridge.getOnReceivedErrorHelper();
+        mOnPageStartedHelper = mTestHelperBridge.getOnPageStartedHelper();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mWebServer.shutdown();
+        super.tearDown();
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStopped"})
+    public void testOnPageLoadStoppedWithLocalUrl() throws Throwable {
+        String url = "file:///android_asset/www/index.html";
+        int currentCallCount = mOnPageFinishedHelper.getCallCount();
+        loadUrlAsync(url);
+
+        mOnPageFinishedHelper.waitForCallback(currentCallCount);
+        assertEquals(url, mOnPageFinishedHelper.getUrl());
+        assertEquals(LoadStatus.FINISHED, mTestHelperBridge.getLoadStatus());
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStopped"})
+    public void testOnPageLoadStoppedWithServer() throws Throwable {
+        final String testHtml = "<html><head>Header</head><body>Body</body></html>";
+        final String testPath = "/test.html";
+
+        final String testUrl = mWebServer.setResponse(testPath, testHtml, null);
+        int currentCallCount = mOnPageFinishedHelper.getCallCount();
+        loadUrlAsync(testUrl);
+
+        mOnPageFinishedHelper.waitForCallback(currentCallCount);
+        assertEquals(testUrl, mOnPageFinishedHelper.getUrl());
+        assertEquals(LoadStatus.FINISHED, mTestHelperBridge.getLoadStatus());
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStopped"})
+    public void testOnPageLoadStoppedWithData() throws Throwable {
+        final String name = "index.html";
+        String fileContent = getFileContent(name);
+        int currentCallCount = mOnPageFinishedHelper.getCallCount();
+        loadDataAsync(null, fileContent, "text/html", false);
+
+        mOnPageFinishedHelper.waitForCallback(currentCallCount);
+        assertEquals("about:blank", mOnPageFinishedHelper.getUrl());
+        assertEquals(LoadStatus.FINISHED, mTestHelperBridge.getLoadStatus());
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStopped"})
+    public void testOnPageLoadStoppedWithInvalidUrl() throws Throwable {
+        String url = "http://localhost/non_existent";
+        int currentCallCount = mOnPageFinishedHelper.getCallCount();
+        int onReceivedErrorCallCount = mOnReceivedErrorHelper.getCallCount();
+        assertEquals(0, mOnReceivedErrorHelper.getCallCount());
+        loadUrlAsync(url);
+
+        mOnReceivedErrorHelper.waitForCallback(onReceivedErrorCallCount,
+                                               1, WAIT_TIMEOUT_MS,
+                                               TimeUnit.MILLISECONDS);
+        mOnPageFinishedHelper.waitForCallback(currentCallCount,
+                                              1, WAIT_TIMEOUT_MS,
+                                              TimeUnit.MILLISECONDS);
+        assertEquals(1, mOnReceivedErrorHelper.getCallCount());
+        assertEquals(url, mOnPageFinishedHelper.getUrl());
+        assertEquals(LoadStatus.FAILED, mTestHelperBridge.getLoadStatus());
+    }
+
+    @MediumTest
+    @Feature({"OnPageLoadStopped"})
+    public void testOnPageLoadStoppedWithStopLoading() throws Throwable {
+        final String testHtml = "<html><head>Header</head><body>Body</body></html>";
+        final String testPath = "/test.html";
+
+        final String testUrl = mWebServer.setResponse(testPath, testHtml, null);
+        int currentCallCount = mOnPageFinishedHelper.getCallCount();
+        int startedCount = mOnPageStartedHelper.getCallCount();
+        loadUrlAsync(testUrl);
+        mOnPageStartedHelper.waitForCallback(startedCount);
+        stopLoading();
+        mOnPageFinishedHelper.waitForCallback(currentCallCount);
+        assertEquals(testUrl, mOnPageFinishedHelper.getUrl());
+        assertEquals(LoadStatus.CANCELLED, mTestHelperBridge.getLoadStatus());
+    }
+}
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnUnhandledKeyEventTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnUnhandledKeyEventTest.java
new file mode 100644 (file)
index 0000000..c457f1a
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright (c) 2014 Intel Corporation. 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.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.KeyEvent;
+
+import org.chromium.base.test.util.Feature;
+import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
+
+/**
+ * Test suite for onUnhandledKeyEvent().
+ */
+public class OnUnhandledKeyEventTest extends XWalkViewTestBase {
+    TestHelperBridge.OverrideOrUnhandledKeyEventHelper mOverrideOrUnhandledKeyEventHelper;
+
+    class TestXWalkUIClientForKeyEvent extends XWalkUIClient {
+        public TestXWalkUIClientForKeyEvent() {
+            super(getXWalkView());
+        }
+
+        @Override
+        public boolean shouldOverrideKeyEvent(XWalkView view, KeyEvent event) {
+            return false;
+        }
+
+        @Override
+        public void onUnhandledKeyEvent(XWalkView view, KeyEvent event) {
+            mTestHelperBridge.overrideOrUnhandledKeyEvent(event);
+        }
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mOverrideOrUnhandledKeyEventHelper = mTestHelperBridge.getOverrideOrUnhandledKeyEventHelper();
+        setUIClient(new TestXWalkUIClientForKeyEvent());
+    }
+
+    @SmallTest
+    @Feature({"onUnhandledKeyEvent"})
+    public void testOnUnhandledKeyEvent() throws Throwable {
+        final String name = "index.html";
+        String fileContent = getFileContent(name);
+        int count = mOverrideOrUnhandledKeyEventHelper.getCallCount();
+        loadDataAsync(null, fileContent, "text/html", false);
+        simulateKeyAction(KeyEvent.ACTION_UP);
+        mOverrideOrUnhandledKeyEventHelper.waitForCallback(count);
+
+        KeyEvent event = mOverrideOrUnhandledKeyEventHelper.getKeyEvent();
+        assertTrue(KeyEvent.ACTION_UP == event.getAction());
+    }
+}
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OpenFileChooserTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OpenFileChooserTest.java
new file mode 100644 (file)
index 0000000..d21edd3
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2014 Intel Corporation. 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.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Test suite for OpenFileChooser().
+ */
+public class OpenFileChooserTest extends XWalkViewTestBase {
+    private TestHelperBridge.OpenFileChooserHelper mOpenFileChooserHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mOpenFileChooserHelper = mTestHelperBridge.getOpenFileChooserHelper();
+    }
+
+    @SmallTest
+    @Feature({"OpenFileChooser"})
+    public void testOpenFileChooser() throws Throwable {
+        final String name = "file_chooser.html";
+        String fileContent = getFileContent(name);
+        int count = mOpenFileChooserHelper.getCallCount();
+
+        loadDataSync(null, fileContent, "text/html", false);
+        clickOnElementId("upload_input", null);
+        mOpenFileChooserHelper.waitForCallback(count);
+        assertNotNull(mOpenFileChooserHelper.getCallback());
+    }
+}
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/ShouldOverrideKeyEventTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/ShouldOverrideKeyEventTest.java
new file mode 100644 (file)
index 0000000..05ab4a8
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (c) 2014 Intel Corporation. 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.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.KeyEvent;
+
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Test suite for shouldOverrideKeyEvent().
+ */
+public class ShouldOverrideKeyEventTest extends XWalkViewTestBase {
+    TestHelperBridge.OverrideOrUnhandledKeyEventHelper mOverrideOrUnhandledKeyEventHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mOverrideOrUnhandledKeyEventHelper = mTestHelperBridge.getOverrideOrUnhandledKeyEventHelper();
+    }
+
+    @SmallTest
+    @Feature({"ShouldOverrideKeyEvent"})
+    public void testShouldOverrideKeyEvent() throws Throwable {
+        final String name = "index.html";
+        String fileContent = getFileContent(name);
+        int count = mOverrideOrUnhandledKeyEventHelper.getCallCount();
+
+        loadDataAsync(null, fileContent, "text/html", false);
+        simulateKeyAction(KeyEvent.ACTION_DOWN);
+        mOverrideOrUnhandledKeyEventHelper.waitForCallback(count);
+
+        KeyEvent event = mOverrideOrUnhandledKeyEventHelper.getKeyEvent();
+        assertTrue(KeyEvent.ACTION_DOWN == event.getAction());
+    }
+}
index 90f615e..a5bed93 100644 (file)
@@ -5,7 +5,9 @@
 
 package org.xwalk.core.xwview.test;
 
+import android.net.Uri;
 import android.util.Log;
+import android.view.KeyEvent;
 import android.webkit.ValueCallback;
 import android.webkit.WebResourceResponse;
 
@@ -22,6 +24,7 @@ import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPage
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
 
+import org.xwalk.core.XWalkUIClient.LoadStatus;
 import org.xwalk.core.XWalkView;
 
 class TestHelperBridge {
@@ -220,7 +223,64 @@ class TestHelperBridge {
         }
     }
 
+    public class OnJavascriptModalDialogHelper extends CallbackHelper {
+        private String mMessage;
+
+        public String getMessage() {
+            assert getCallCount() > 0;
+            return mMessage;
+        }
+
+        public void notifyCalled(String message) {
+            mMessage = message;
+            notifyCalled();
+        }
+    }
+
+    public class OpenFileChooserHelper extends CallbackHelper {
+        private ValueCallback<Uri> mCallback;
+
+        public ValueCallback<Uri> getCallback() {
+            assert getCallCount() > 0;
+            return mCallback;
+        }
+
+        public void notifyCalled(ValueCallback<Uri> callback) {
+            mCallback = callback;
+            notifyCalled();
+        }
+    }
+
+    public class OnFullscreenToggledHelper extends CallbackHelper {
+        private boolean mEnterFullscreen = false;
+
+        public boolean getEnterFullscreen() {
+            assert getCallCount() > 0;
+            return mEnterFullscreen;
+        }
+
+        public void notifyCalled(boolean enterFullscreen) {
+            mEnterFullscreen = enterFullscreen;
+            notifyCalled();
+        }
+    }
+
+    public class OverrideOrUnhandledKeyEventHelper extends CallbackHelper {
+        private KeyEvent mEvent;
+
+        public KeyEvent getKeyEvent() {
+            assert getCallCount() > 0;
+            return mEvent;
+        }
+
+        public void notifyCalled(KeyEvent event) {
+            mEvent = event;
+            notifyCalled();
+        }
+    }
+
     private String mChangedTitle;
+    private LoadStatus mLoadStatus;
     private final OnPageStartedHelper mOnPageStartedHelper;
     private final OnPageFinishedHelper mOnPageFinishedHelper;
     private final OnReceivedErrorHelper mOnReceivedErrorHelper;
@@ -235,6 +295,10 @@ class TestHelperBridge {
     private final ShouldOverrideUrlLoadingHelper mShouldOverrideUrlLoadingHelper;
     private final OnScaleChangedHelper mOnScaleChangedHelper;
     private final OnRequestFocusHelper mOnRequestFocusHelper;
+    private final OnJavascriptModalDialogHelper mOnJavascriptModalDialogHelper;
+    private final OpenFileChooserHelper mOpenFileChooserHelper;
+    private final OnFullscreenToggledHelper mOnFullscreenToggledHelper;
+    private final OverrideOrUnhandledKeyEventHelper mOverrideOrUnhandledKeyEventHelper;
 
     public TestHelperBridge() {
         mOnPageStartedHelper = new OnPageStartedHelper();
@@ -249,6 +313,10 @@ class TestHelperBridge {
         mShouldOverrideUrlLoadingHelper = new ShouldOverrideUrlLoadingHelper();
         mOnScaleChangedHelper = new OnScaleChangedHelper();
         mOnRequestFocusHelper = new OnRequestFocusHelper();
+        mOnJavascriptModalDialogHelper = new OnJavascriptModalDialogHelper();
+        mOpenFileChooserHelper = new OpenFileChooserHelper();
+        mOnFullscreenToggledHelper = new OnFullscreenToggledHelper();
+        mOverrideOrUnhandledKeyEventHelper = new OverrideOrUnhandledKeyEventHelper();
     }
 
     public OnPageStartedHelper getOnPageStartedHelper() {
@@ -299,6 +367,22 @@ class TestHelperBridge {
         return mOnRequestFocusHelper;
     }
 
+    public OnJavascriptModalDialogHelper getOnJavascriptModalDialogHelper() {
+        return mOnJavascriptModalDialogHelper;
+    }
+
+    public OpenFileChooserHelper getOpenFileChooserHelper() {
+        return mOpenFileChooserHelper;
+    }
+
+    public OnFullscreenToggledHelper getOnFullscreenToggledHelper() {
+        return mOnFullscreenToggledHelper;
+    }
+
+    public OverrideOrUnhandledKeyEventHelper getOverrideOrUnhandledKeyEventHelper() {
+        return mOverrideOrUnhandledKeyEventHelper;
+    }
+
     public void onTitleChanged(String title) {
         mChangedTitle = title;
         mOnTitleUpdatedHelper.notifyCalled(title);
@@ -312,10 +396,15 @@ class TestHelperBridge {
         mOnPageStartedHelper.notifyCalled(url);
     }
 
-    public void onPageFinished(String url) {
+    public void onPageFinished(String url, LoadStatus status) {
+        mLoadStatus = status;
         mOnPageFinishedHelper.notifyCalled(url);
     }
 
+    public LoadStatus getLoadStatus() {
+        return mLoadStatus;
+    }
+
     public void onReceivedLoadError(int errorCode, String description, String failingUrl) {
         mOnReceivedErrorHelper.notifyCalled(errorCode, description, failingUrl);
     }
@@ -352,4 +441,22 @@ class TestHelperBridge {
     public void onRequestFocus() {
         mOnRequestFocusHelper.notifyCalled(true);
     }
+
+    public boolean onJavascriptModalDialog(String message) {
+        mOnJavascriptModalDialogHelper.notifyCalled(message);
+        return true;
+    }
+
+    public void openFileChooser(ValueCallback<Uri> uploadFile) {
+        mOpenFileChooserHelper.notifyCalled(uploadFile);
+    }
+
+    public void onFullscreenToggled(boolean enterFullscreen) {
+        mOnFullscreenToggledHelper.notifyCalled(enterFullscreen);
+    }
+
+    public boolean overrideOrUnhandledKeyEvent(KeyEvent event) {
+        mOverrideOrUnhandledKeyEventHelper.notifyCalled(event);
+        return true;
+    }
 }
index 01ae91b..6537905 100644 (file)
@@ -7,8 +7,11 @@ package org.xwalk.core.xwview.test;
 
 import android.app.Activity;
 import android.content.Context;
+import android.net.Uri;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
+import android.view.KeyEvent;
+import android.webkit.ValueCallback;
 import android.webkit.WebResourceResponse;
 
 import java.io.InputStream;
@@ -25,6 +28,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.xwalk.core.XWalkJavascriptResult;
 import org.xwalk.core.XWalkNavigationHistory;
 import org.xwalk.core.XWalkNavigationItem;
 import org.xwalk.core.XWalkResourceClient;
@@ -54,7 +58,7 @@ public class XWalkViewTestBase
 
         @Override
         public void onPageLoadStopped(XWalkView view, String url, LoadStatus status) {
-            mInnerContentsClient.onPageFinished(url);
+            mInnerContentsClient.onPageFinished(url, status);
         }
 
         @Override
@@ -76,6 +80,29 @@ public class XWalkViewTestBase
         public void onRequestFocus(XWalkView view) {
             mInnerContentsClient.onRequestFocus();
         }
+
+        @Override
+        public boolean onJavascriptModalDialog(XWalkView view,
+                XWalkUIClient.JavascriptMessageType type, String url, String message,
+                        String defaultValue, XWalkJavascriptResult result) {
+            return mInnerContentsClient.onJavascriptModalDialog(message);
+        }
+
+        @Override
+        public void openFileChooser(XWalkView view, ValueCallback<Uri> uploadFile,
+                String acceptType, String capture) {
+            mInnerContentsClient.openFileChooser(uploadFile);
+        }
+
+        @Override
+        public void onFullscreenToggled(XWalkView view, boolean enterFullscreen) {
+            mInnerContentsClient.onFullscreenToggled(enterFullscreen);
+        }
+
+        @Override
+        public boolean shouldOverrideKeyEvent(XWalkView view, KeyEvent event) {
+            return mInnerContentsClient.overrideOrUnhandledKeyEvent(event);
+        }
     }
 
     class TestXWalkUIClient extends TestXWalkUIClientBase {
@@ -524,4 +551,26 @@ public class XWalkViewTestBase
             t.printStackTrace();
         }
     }
+
+    public void simulateKeyAction(final int action) {
+        new Thread(new Runnable() {
+            public void run() {
+                try {
+                    getInstrumentation().sendKeySync(new KeyEvent(action,
+                            KeyEvent.KEYCODE_DPAD_CENTER));
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }).start();
+    }
+
+    protected void stopLoading() throws Exception {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mXWalkView.stopLoading();
+            }
+        });
+    }
 }
diff --git a/src/xwalk/test/android/data/file_chooser.html b/src/xwalk/test/android/data/file_chooser.html
new file mode 100644 (file)
index 0000000..6d0e485
--- /dev/null
@@ -0,0 +1,8 @@
+<html>
+<body >
+  <div style="display: block; width: 100px; height: 20px; overflow: hidden;">
+
+    <input type="file" id="upload_input" name="upload"  />
+  </div>
+</body>
+</html>
diff --git a/src/xwalk/test/android/data/fullscreen_togged.html b/src/xwalk/test/android/data/fullscreen_togged.html
new file mode 100644 (file)
index 0000000..eea9ece
--- /dev/null
@@ -0,0 +1,12 @@
+<html>
+<head>
+<script>
+function launchFullscreen(element) {
+  element.webkitRequestFullscreen();
+}
+</script>
+</head>
+<body>
+  <button id="fullscreen_toggled" onclick="launchFullscreen(document.documentElement);">Launch Fullscreen</button>
+</body>
+</html>
diff --git a/src/xwalk/test/android/data/js_modal_dialog.html b/src/xwalk/test/android/data/js_modal_dialog.html
new file mode 100644 (file)
index 0000000..5e0d4ac
--- /dev/null
@@ -0,0 +1,5 @@
+<html>
+    <body>
+        <a href=# onclick="alert('hello')" id="js_modal_dialog"> Click Me</a>
+    </body>
+</html>
index 467e20d..0cc9217 100644 (file)
         'runtime/browser/android/xwalk_login_delegate.h',
         'runtime/browser/android/xwalk_path_helper.cc',
         'runtime/browser/android/xwalk_path_helper.h',
+        'runtime/browser/android/xwalk_icon_helper.cc',
+        'runtime/browser/android/xwalk_icon_helper.h',
         'runtime/browser/android/xwalk_request_interceptor.cc',
         'runtime/browser/android/xwalk_request_interceptor.h',
         'runtime/browser/android/xwalk_settings.cc',
index 25c88b9..bbc2ee9 100644 (file)
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/add_js_interface.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/echo.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/echoSync.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/file_chooser.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/framesEcho.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/fullscreen_enter_exit.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/fullscreen_togged.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/index.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/js_modal_dialog.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/profile.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/scale_changed.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/window.close.html',
             'test/android/data/add_js_interface.html',
             'test/android/data/echo.html',
             'test/android/data/echoSync.html',
+            'test/android/data/file_chooser.html',
             'test/android/data/framesEcho.html',
             'test/android/data/fullscreen_enter_exit.html',
+            'test/android/data/fullscreen_togged.html',
             'test/android/data/index.html',
+            'test/android/data/js_modal_dialog.html',
             'test/android/data/profile.html',
             'test/android/data/scale_changed.html',
             'test/android/data/window.close.html',