Upstream version 6.35.131.0 63/20363/1 submit/tizen/20140506.123310
authorEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Mon, 5 May 2014 13:34:21 +0000 (13:34 +0000)
committerEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Mon, 5 May 2014 13:34:21 +0000 (13:34 +0000)
Upstream commit-id 5db4895fc0a9d4b51cfc75f69594132e2d35ce22

Change-Id: Ic58f01a75ede1c7fc783cfe3ef0ad862d1ad6a05
Signed-off-by: Eurogiciel-BOT <eurogiciel.tizen@gmail.com>
226 files changed:
packaging/crosswalk.spec
src/base/android/java/src/org/chromium/base/ApplicationStatus.java
src/base/message_loop/message_pump_ozone.cc
src/base/message_loop/message_pump_ozone.h
src/build/util/LASTCHANGE
src/components/nacl.gyp
src/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
src/content/renderer/web_preferences.cc
src/v8/build/features.gypi
src/v8/src/arm/lithium-codegen-arm.cc
src/v8/src/code-stubs.cc
src/v8/src/code-stubs.h
src/v8/src/hydrogen-instructions.h
src/v8/src/hydrogen.cc
src/v8/src/ia32/lithium-codegen-ia32.cc
src/v8/src/ia32/lithium-ia32.cc
src/v8/src/log.cc
src/v8/src/log.h
src/v8/src/runtime.js
src/v8/src/third_party/xdk/xdk-agent.cc [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-agent.h [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-code-map.cc [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-code-map.h [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-types.h [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-v8.cc [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-v8.gyp [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-v8.h [new file with mode: 0644]
src/v8/src/x64/assembler-x64.cc
src/v8/src/x64/lithium-codegen-x64.cc
src/v8/src/x64/lithium-x64.cc
src/v8/test/mjsunit/simd/builtin_operator.js [new file with mode: 0644]
src/v8/test/mjsunit/simd/conversions.js [new file with mode: 0644]
src/v8/tools/check-static-initializers.sh
src/v8/tools/gyp/v8.gyp
src/xwalk/DEPS.xwalk
src/xwalk/VERSION
src/xwalk/app/android/app_hello_world/AndroidManifest.xml
src/xwalk/app/android/app_hello_world/res/values/strings.xml
src/xwalk/app/android/app_template/AndroidManifest.xml
src/xwalk/app/android/app_template/res/drawable/launchscreen_bg.xml [new file with mode: 0644]
src/xwalk/app/android/app_template/res/values/strings.xml
src/xwalk/app/android/runtime_activity/src/org/xwalk/app/XWalkRuntimeActivityBase.java
src/xwalk/app/android/runtime_client/src/org/xwalk/app/runtime/XWalkRuntimeClient.java
src/xwalk/app/android/runtime_client/src/org/xwalk/app/runtime/XWalkRuntimeLibraryException.java
src/xwalk/app/android/runtime_client_embedded_shell/AndroidManifest.xml
src/xwalk/app/android/runtime_client_shell/AndroidManifest.xml
src/xwalk/app/tools/android/customize.py
src/xwalk/app/tools/android/customize_launch_screen.py [new file with mode: 0755]
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.cc
src/xwalk/application/browser/application.h
src/xwalk/application/browser/application_protocols.cc
src/xwalk/application/browser/application_service.cc
src/xwalk/application/browser/application_service.h
src/xwalk/application/browser/application_system.cc
src/xwalk/application/browser/installer/tizen/service_package_installer.cc
src/xwalk/application/browser/linux/installed_application_object.cc
src/xwalk/application/browser/linux/installed_application_object.h
src/xwalk/application/browser/linux/installed_applications_manager.cc
src/xwalk/application/browser/linux/installed_applications_manager.h
src/xwalk/application/browser/linux/running_application_object.cc
src/xwalk/application/browser/linux/running_application_object.h
src/xwalk/application/browser/linux/running_applications_manager.cc
src/xwalk/application/common/application_data.cc
src/xwalk/application/common/application_data.h
src/xwalk/application/common/application_manifest_constants.cc
src/xwalk/application/common/application_manifest_constants.h
src/xwalk/application/common/application_resource.cc
src/xwalk/application/common/application_resource.h
src/xwalk/application/common/manifest.cc
src/xwalk/application/common/manifest.h
src/xwalk/application/common/manifest_handler.cc
src/xwalk/application/common/manifest_handlers/tizen_metadata_handler.cc [new file with mode: 0644]
src/xwalk/application/common/manifest_handlers/tizen_metadata_handler.h [new file with mode: 0644]
src/xwalk/application/common/security_policy.cc [new file with mode: 0644]
src/xwalk/application/common/security_policy.h [new file with mode: 0644]
src/xwalk/application/extension/application_widget_storage.cc
src/xwalk/application/tools/linux/xwalk_extension_process_launcher.cc
src/xwalk/application/tools/linux/xwalk_launcher_main.cc
src/xwalk/application/tools/tizen/xwalk_pkg_helper.cc
src/xwalk/application/tools/tizen/xwalk_pkg_installer.cc [new file with mode: 0644]
src/xwalk/application/tools/tizen/xwalk_pkg_installer.h [new file with mode: 0644]
src/xwalk/application/tools/tizen/xwalk_tizen_helper.gyp
src/xwalk/application/xwalk_application.gypi
src/xwalk/build/android/envsetup.sh
src/xwalk/build/android/generate_app_packaging_tool.py [changed mode: 0644->0755]
src/xwalk/build/android/generate_xwalk_core_library.py
src/xwalk/build/android/merge_jars.py [new file with mode: 0755]
src/xwalk/build/system.gyp
src/xwalk/extensions/android/java/src/org/xwalk/core/extensions/XWalkExtensionAndroid.java
src/xwalk/extensions/browser/xwalk_extension_process_host.cc
src/xwalk/extensions/common/android/xwalk_extension_android.cc
src/xwalk/packaging/crosswalk.spec
src/xwalk/runtime/android/core/src/org/xwalk/core/AndroidProtocolHandler.java
src/xwalk/runtime/android/core/src/org/xwalk/core/ErrorCodeConversionHelper.java [new file with mode: 0644]
src/xwalk/runtime/android/core/src/org/xwalk/core/JavascriptInterface.java [new file with mode: 0644]
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkContent.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkContentVideoViewClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkContentsClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkContentsClientBridge.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkCookieManager.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkDevToolsServer.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkGeolocationPermissions.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkHttpAuthHandler.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkLaunchScreenManager.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkNavigationHandlerImpl.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkNavigationHistory.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkNavigationItem.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkNotificationServiceImpl.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkPreferences.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkResourceClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkResourceClientImpl.java [deleted file]
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkSettings.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkUIClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkUIClientImpl.java [deleted file]
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkView.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkViewDelegate.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkWebChromeClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkWebContentsDelegate.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkWebContentsDelegateAdapter.java
src/xwalk/runtime/android/core/src/org/xwalk/core/extension/api/presentation/XWalkPresentationContent.java
src/xwalk/runtime/android/core/src/org/xwalk/core/package.html [new file with mode: 0644]
src/xwalk/runtime/android/core/strings/android_xwalk_strings.grd
src/xwalk/runtime/android/core_library_empty/AndroidManifest.xml [new file with mode: 0644]
src/xwalk/runtime/android/core_library_empty/src/README.md [new file with mode: 0644]
src/xwalk/runtime/android/core_shell/AndroidManifest.xml
src/xwalk/runtime/android/core_shell/src/org/xwalk/core/xwview/shell/XWalkViewShellActivity.java
src/xwalk/runtime/android/runtime/src/org/xwalk/runtime/MixedContext.java
src/xwalk/runtime/android/runtime/src/org/xwalk/runtime/XWalkCoreProviderImpl.java
src/xwalk/runtime/android/runtime/src/org/xwalk/runtime/XWalkManifestReader.java [deleted file]
src/xwalk/runtime/android/runtime/src/org/xwalk/runtime/XWalkRuntimeTestHelper.java
src/xwalk/runtime/android/runtime_shell/AndroidManifest.xml
src/xwalk/runtime/android/sample/AndroidManifest.xml [new file with mode: 0644]
src/xwalk/runtime/android/sample/assets/index.html [new file with mode: 0644]
src/xwalk/runtime/android/sample/assets/manifest.json [new file with mode: 0644]
src/xwalk/runtime/android/sample/assets/pause_timers.html [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/drawable-hdpi/crosswalk.png [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/drawable-ldpi/crosswalk.png [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/drawable-mdpi/crosswalk.png [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/drawable-xhdpi/crosswalk.png [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/layout/container.xml [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/layout/navigation_layout.xml [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/layout/pause_timers_layout.xml [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/layout/xwview_layout.xml [new file with mode: 0644]
src/xwalk/runtime/android/sample/res/values/strings.xml [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/LoadAppFromManifestActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/MultiXWalkViewActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnHideOnShowActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/PauseTimersActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/ResourceAndUIClientsActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkEmbeddingAPISample.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkNavigationActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkPreferencesActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkViewWithLayoutActivity.java [new file with mode: 0644]
src/xwalk/runtime/app/android/xwalk_jni_registrar.cc
src/xwalk/runtime/browser/android/renderer_host/xwalk_render_view_host_ext.cc
src/xwalk/runtime/browser/android/renderer_host/xwalk_render_view_host_ext.h
src/xwalk/runtime/browser/android/xwalk_content.cc
src/xwalk/runtime/browser/android/xwalk_content.h
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_dev_tools_server.cc
src/xwalk/runtime/browser/android/xwalk_http_auth_handler.cc
src/xwalk/runtime/browser/android/xwalk_settings.cc
src/xwalk/runtime/browser/android/xwalk_settings.h
src/xwalk/runtime/browser/android/xwalk_view_delegate.cc [new file with mode: 0644]
src/xwalk/runtime/browser/android/xwalk_view_delegate.h [new file with mode: 0644]
src/xwalk/runtime/browser/android/xwalk_web_contents_delegate.cc
src/xwalk/runtime/browser/runtime_file_select_helper.cc
src/xwalk/runtime/browser/runtime_platform_util_tizen.cc
src/xwalk/runtime/browser/tizen/tizen_locale_listener.cc [new file with mode: 0644]
src/xwalk/runtime/browser/tizen/tizen_locale_listener.h [new file with mode: 0644]
src/xwalk/runtime/browser/ui/native_app_window_tizen.cc
src/xwalk/runtime/browser/xwalk_content_browser_client.cc
src/xwalk/runtime/browser/xwalk_content_browser_client.h
src/xwalk/runtime/browser/xwalk_render_message_filter.cc
src/xwalk/runtime/browser/xwalk_runner.cc
src/xwalk/runtime/browser/xwalk_runner.h
src/xwalk/runtime/browser/xwalk_runner_tizen.cc
src/xwalk/runtime/browser/xwalk_runner_tizen.h
src/xwalk/runtime/common/android/xwalk_render_view_messages.h
src/xwalk/runtime/common/xwalk_common_messages.h
src/xwalk/runtime/common/xwalk_localized_error.cc [new file with mode: 0644]
src/xwalk/runtime/common/xwalk_localized_error.h [new file with mode: 0644]
src/xwalk/runtime/renderer/android/xwalk_render_process_observer.cc
src/xwalk/runtime/renderer/android/xwalk_render_process_observer.h
src/xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.cc [new file with mode: 0644]
src/xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.h [new file with mode: 0644]
src/xwalk/runtime/renderer/xwalk_content_renderer_client.cc
src/xwalk/runtime/renderer/xwalk_content_renderer_client.h
src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.cc
src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.h
src/xwalk/runtime/resources/xwalk_resources.grd
src/xwalk/test/android/core/javatests/AndroidManifest.xml
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/CookieManagerTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/GeolocationPermissionTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/HandleActionUriTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/LoadUrlTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/NullContentsClient.java [deleted file]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnPageFinishedTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/ReloadTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/RendererResponsivenessTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/SaveRestoreStateTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/SetAppCacheEnabledTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/SetDomStorageEnabledTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/SetNetworkAvailableTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/ShouldInterceptLoadRequestTest.java
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/UserAgentTest.java
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/XWalkViewTestBase.java
src/xwalk/test/android/data/www/cross_origin.html [new file with mode: 0644]
src/xwalk/test/android/data/www/manifest_without_xwalk_hosts.json [new file with mode: 0644]
src/xwalk/test/android/data/www/manifest_xwalk_hosts.json [new file with mode: 0644]
src/xwalk/test/android/runtime/javatests/AndroidManifest.xml
src/xwalk/test/android/runtime_client/javatests/AndroidManifest.xml
src/xwalk/test/android/runtime_client/javatests/src/org/xwalk/runtime/client/test/CrossOriginXhrTest.java [new file with mode: 0644]
src/xwalk/test/android/runtime_client_embedded/javatests/AndroidManifest.xml
src/xwalk/test/android/runtime_client_embedded/javatests/src/org/xwalk/runtime/client/embedded/test/CrossOriginXhrTest.java [new file with mode: 0644]
src/xwalk/test/android/util/runtime_client/src/org/xwalk/test/util/RuntimeClientApiTestBase.java
src/xwalk/xwalk.gyp
src/xwalk/xwalk_android.gypi
src/xwalk/xwalk_android_tests.gypi
src/xwalk/xwalk_core_library_android.gypi

index f3cad41..292de2f 100644 (file)
@@ -2,7 +2,7 @@
 %bcond_with wayland
 
 Name:           crosswalk
-Version:        6.35.121.0
+Version:        6.35.131.0
 Release:        0
 Summary:        Crosswalk is an app runtime based on Chromium
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -50,6 +50,7 @@ BuildRequires:  pkgconfig(libxml-2.0)
 BuildRequires:  pkgconfig(libxslt)
 BuildRequires:  pkgconfig(pango)
 BuildRequires:  pkgconfig(pkgmgr-info)
+BuildRequires:  pkgconfig(pkgmgr-installer)
 BuildRequires:  pkgconfig(pkgmgr-parser)
 BuildRequires:  pkgconfig(nspr)
 BuildRequires:  pkgconfig(nss)
@@ -141,7 +142,7 @@ if [ -n "${BUILDDIR_NAME}" ]; then
 fi
 
 %if %{with wayland}
-GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1 -Denable_xdg_shell=1"
 %endif
 
 # --no-parallel is added because chroot does not mount a /dev/shm, this will
index e055585..b4b79f1 100644 (file)
@@ -190,6 +190,9 @@ public class ApplicationStatus {
         sCachedApplicationState = null;
 
         ActivityInfo info = sActivityInfo.get(activity);
+        // Ignore status from none tracked activitys.
+        if (info == null) return;
+
         info.setStatus(newState);
 
         // Notify all state observers that are specifically listening to this activity.
index b262291..9941d00 100644 (file)
@@ -16,12 +16,24 @@ MessagePumpOzone::MessagePumpOzone()
 MessagePumpOzone::~MessagePumpOzone() {
 }
 
-void MessagePumpOzone::AddObserver(MessagePumpObserver* /* observer */) {
-  NOTIMPLEMENTED();
+void MessagePumpOzone::AddObserver(MessagePumpObserver* observer) {
+  observers_.AddObserver(observer);
 }
 
-void MessagePumpOzone::RemoveObserver(MessagePumpObserver* /* observer */) {
-  NOTIMPLEMENTED();
+void MessagePumpOzone::RemoveObserver(MessagePumpObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void MessagePumpOzone::WillProcessEvent(const NativeEvent& event) {
+  FOR_EACH_OBSERVER(MessagePumpObserver,
+                    observers_,
+                    WillProcessEvent(event));
+}
+
+void MessagePumpOzone::DidProcessEvent(const NativeEvent& event) {
+  FOR_EACH_OBSERVER(MessagePumpObserver,
+                    observers_,
+                    DidProcessEvent(event));
 }
 
 // static
@@ -33,20 +45,24 @@ MessagePumpOzone* MessagePumpOzone::Current() {
 void MessagePumpOzone::AddDispatcherForRootWindow(
     MessagePumpDispatcher* dispatcher) {
   // Only one root window is supported.
-  DCHECK(dispatcher_.size() == 0);
-  dispatcher_.insert(dispatcher_.begin(),dispatcher);
+  DCHECK_EQ(dispatcher_.size(), 0);
+  dispatcher_.insert(dispatcher_.begin(), dispatcher);
 }
 
 void MessagePumpOzone::RemoveDispatcherForRootWindow(
       MessagePumpDispatcher* dispatcher) {
-  DCHECK(dispatcher_.size() == 1);
+  DCHECK_EQ(dispatcher_.size(), 1);
   dispatcher_.pop_back();
 }
 
 uint32_t MessagePumpOzone::Dispatch(const NativeEvent& dev) {
-  if (dispatcher_.size() > 0)
-    return dispatcher_[0]->Dispatch(dev);
-  return POST_DISPATCH_NONE;
+  uint32_t result = POST_DISPATCH_NONE;
+  WillProcessEvent(dev);
+  if (!dispatcher_.empty()) {
+    result = dispatcher_[0]->Dispatch(dev);
+  }
+  DidProcessEvent(dev);
+  return result;
 }
 
 // This code assumes that the caller tracks the lifetime of the |dispatcher|.
index 30db9df..bf8f69b 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_OZONE_H_
 #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_OZONE_H_
 
+#include <vector>
+
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_pump_dispatcher.h"
@@ -39,7 +41,13 @@ class BASE_EXPORT MessagePumpOzone : public MessagePumpLibevent,
   // Overridden from MessagePumpDispatcher.
   virtual uint32_t Dispatch(const NativeEvent& event) OVERRIDE;
 
+  // List of observers.
+  ObserverList<MessagePumpObserver> observers_;
+
  private:
+  void WillProcessEvent(const NativeEvent& event);
+  void DidProcessEvent(const NativeEvent& event);
+
   std::vector<MessagePumpDispatcher*> dispatcher_;
 
   DISALLOW_COPY_AND_ASSIGN(MessagePumpOzone);
index 7bf9b3d..7be6be0 100644 (file)
@@ -1 +1 @@
-LASTCHANGE=261600
+LASTCHANGE=260856
index 3194b0a..160b934 100644 (file)
@@ -78,6 +78,7 @@
           },
           'dependencies': [
             '../base/base.gyp:base',
+            '../base/base.gyp:base_static',
             '../ipc/ipc.gyp:ipc',
             '../ppapi/native_client/src/trusted/plugin/plugin.gyp:ppGoogleNaClPluginChrome',
             '../ppapi/ppapi_internal.gyp:ppapi_shared',
index 89857ff..3b75d1f 100644 (file)
@@ -67,7 +67,7 @@ public class ResourceExtractor {
 
             String timestampFile = checkPakTimestamp();
             if (timestampFile != null) {
-                deleteFiles();
+                deleteFiles(mContext);
             }
 
             SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
@@ -185,7 +185,7 @@ public class ResourceExtractor {
                 // returning null? It might be useful to gather UMA here too to track if
                 // this happens with regularity.
                 Log.w(LOGTAG, "Exception unpacking required pak resources: " + e.getMessage());
-                deleteFiles();
+                deleteFiles(mContext);
                 return null;
             }
 
@@ -307,9 +307,9 @@ public class ResourceExtractor {
     }
 
     private ResourceExtractor(Context context) {
-        mContext = context.getApplicationContext();
-        mAppDataDir = getAppDataDir();
-        mOutputDir = getOutputDir();
+        mContext = context;
+        mAppDataDir = getAppDataDirFromContext(mContext);
+        mOutputDir = getOutputDirFromContext(mContext);
     }
 
     public void waitForCompletion() {
@@ -321,13 +321,17 @@ public class ResourceExtractor {
 
         try {
             mExtractTask.get();
+            // ResourceExtractor is not needed any more.
+            // Release static objects to avoid leak of Context.
+            sIntercepter = null;
+            sInstance = null;
         } catch (CancellationException e) {
             // Don't leave the files in an inconsistent state.
-            deleteFiles();
+            deleteFiles(mContext);
         } catch (ExecutionException e2) {
-            deleteFiles();
+            deleteFiles(mContext);
         } catch (InterruptedException e3) {
-            deleteFiles();
+            deleteFiles(mContext);
         }
     }
 
@@ -349,12 +353,12 @@ public class ResourceExtractor {
         mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
-    private File getAppDataDir() {
-        return new File(PathUtils.getDataDirectory(mContext));
+    public static File getAppDataDirFromContext(Context context) {
+        return new File(PathUtils.getDataDirectory(context.getApplicationContext()));
     }
 
-    private File getOutputDir() {
-        return new File(getAppDataDir(), "paks");
+    public static File getOutputDirFromContext(Context context) {
+        return new File(getAppDataDirFromContext(context), "paks");
     }
 
     /**
@@ -364,12 +368,12 @@ public class ResourceExtractor {
      * lead to malfunction/UX misbehavior. So, we regard failing to update them
      * as an error.
      */
-    private void deleteFiles() {
-        File icudata = new File(getAppDataDir(), ICU_DATA_FILENAME);
+    public static void deleteFiles(Context context) {
+        File icudata = new File(getAppDataDirFromContext(context), ICU_DATA_FILENAME);
         if (icudata.exists() && !icudata.delete()) {
             Log.e(LOGTAG, "Unable to remove the icudata " + icudata.getName());
         }
-        File dir = getOutputDir();
+        File dir = getOutputDirFromContext(context);
         if (dir.exists()) {
             File[] files = dir.listFiles();
             for (File file : files) {
index 7f6aea9..33882e3 100644 (file)
@@ -323,9 +323,6 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
   // Scrollbars should not be stylable.
   settings->setAllowCustomScrollbarInMainFrame(false);
 
-  // Don't auto play music on Tizen devices.
-  settings->setMediaPlaybackRequiresUserGesture(true);
-
   // IME support
   settings->setAutoZoomFocusedNodeToLegibleScale(true);
 
index f0e7212..af4b41b 100644 (file)
@@ -43,6 +43,9 @@
 
     'v8_use_snapshot%': 'true',
 
+    # Enable XDK profiling support by default.
+    'v8_enable_xdkprof': 1,
+
     # With post mortem support enabled, metadata is embedded into libv8 that
     # describes various parameters of the VM for use by debuggers. See
     # tools/gen-postmortem-metadata.py for details.
index f2abdd3..b04c970 100644 (file)
@@ -2243,6 +2243,18 @@ void LCodeGen::DoBranch(LBranch* instr) {
         __ b(eq, instr->TrueLabel(chunk_));
       }
 
+      if (expected.Contains(ToBooleanStub::FLOAT32x4)) {
+        // Float32x4 value -> true.
+        __ CompareInstanceType(map, ip, FLOAT32x4_TYPE);
+        __ b(eq, instr->TrueLabel(chunk_));
+      }
+
+      if (expected.Contains(ToBooleanStub::INT32x4)) {
+        // Int32x4 value -> true.
+        __ CompareInstanceType(map, ip, INT32x4_TYPE);
+        __ b(eq, instr->TrueLabel(chunk_));
+      }
+
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
         // heap number -> false iff +0, -0, or NaN.
         DwVfpRegister dbl_scratch = double_scratch0();
index 0620362..48ddf0c 100644 (file)
@@ -640,6 +640,8 @@ void ToBooleanStub::Types::Print(StringStream* stream) const {
   if (Contains(STRING)) printer.Add("String");
   if (Contains(SYMBOL)) printer.Add("Symbol");
   if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
+  if (Contains(FLOAT32x4)) printer.Add("Float32x4");
+  if (Contains(INT32x4)) printer.Add("Int32x4");
   stream->Add(")");
 }
 
@@ -667,6 +669,12 @@ bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
   } else if (object->IsSymbol()) {
     Add(SYMBOL);
     return true;
+  } else if (object->IsFloat32x4()) {
+    Add(FLOAT32x4);
+    return true;
+  } else if (object->IsInt32x4()) {
+    Add(INT32x4);
+    return true;
   } else if (object->IsHeapNumber()) {
     ASSERT(!object->IsUndetectableObject());
     Add(HEAP_NUMBER);
@@ -684,6 +692,8 @@ bool ToBooleanStub::Types::NeedsMap() const {
   return Contains(ToBooleanStub::SPEC_OBJECT)
       || Contains(ToBooleanStub::STRING)
       || Contains(ToBooleanStub::SYMBOL)
+      || Contains(ToBooleanStub::FLOAT32x4)
+      || Contains(ToBooleanStub::INT32x4)
       || Contains(ToBooleanStub::HEAP_NUMBER);
 }
 
index 5a88942..42f3a22 100644 (file)
@@ -2335,19 +2335,20 @@ class ToBooleanStub: public HydrogenCodeStub {
     STRING,
     SYMBOL,
     HEAP_NUMBER,
+    FLOAT32x4,
+    INT32x4,
     NUMBER_OF_TYPES
   };
 
   // At most 8 different types can be distinguished, because the Code object
   // only has room for a single byte to hold a set of these types. :-P
-  STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
+  STATIC_ASSERT(NUMBER_OF_TYPES <= 10);
 
-  class Types : public EnumSet<Type, byte> {
+  class Types : public EnumSet<Type, int> {
    public:
-    Types() : EnumSet<Type, byte>(0) {}
-    explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
+    Types() : EnumSet<Type, int>(0) {}
+    explicit Types(int bits) : EnumSet<Type, int>(bits) {}
 
-    byte ToByte() const { return ToIntegral(); }
     void Print(StringStream* stream) const;
     bool UpdateStatus(Handle<Object> object);
     bool NeedsMap() const;
@@ -2360,7 +2361,7 @@ class ToBooleanStub: public HydrogenCodeStub {
   explicit ToBooleanStub(Types types = Types())
       : types_(types) { }
   explicit ToBooleanStub(ExtraICState state)
-      : types_(static_cast<byte>(state)) { }
+      : types_(static_cast<int>(state)) { }
 
   bool UpdateStatus(Handle<Object> object);
   Types GetTypes() { return types_; }
index fed7e52..3f4bef0 100644 (file)
@@ -5895,6 +5895,17 @@ class HObjectAccess V8_FINAL {
                          Representation::Integer32());
   }
 
+  static HObjectAccess ForSIMD128XYLanes() {
+    return HObjectAccess(
+        kDouble, Float32x4::kValueOffset, Representation::Double());
+  }
+
+  static HObjectAccess ForSIMD128ZWLanes() {
+    return HObjectAccess(kDouble,
+                         Float32x4::kValueOffset + kDoubleSize,
+                         Representation::Double());
+  }
+
   static HObjectAccess ForElementsPointer() {
     return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
   }
index e24af9a..ee60708 100644 (file)
@@ -8888,7 +8888,33 @@ HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
   Add<HStoreNamedField>(elements,
       HObjectAccess::ForFixedArrayLength(),
       length);
+
   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
+  if (IsFixedFloat32x4ElementsKind(fixed_elements_kind)) {
+    if (CPU::SupportsSIMD128InCrankshaft()) {
+      filler = AddUncasted<HNullarySIMDOperation>(kFloat32x4Zero);
+    } else {
+      HValue* size = Add<HConstant>(Float32x4::kSize);
+      filler = Add<HAllocate>(size, HType::Tagged(), NOT_TENURED,
+          Float32x4::kInstanceType);
+      AddStoreMapConstant(filler, isolate()->factory()->float32x4_map());
+      HValue* zero = Add<HConstant>(static_cast<double>(0.0));
+      Add<HStoreNamedField>(filler, HObjectAccess::ForSIMD128XYLanes(), zero);
+      Add<HStoreNamedField>(filler, HObjectAccess::ForSIMD128ZWLanes(), zero);
+    }
+  } else if (IsFixedInt32x4ElementsKind(fixed_elements_kind)) {
+    if (CPU::SupportsSIMD128InCrankshaft()) {
+      filler = AddUncasted<HNullarySIMDOperation>(kInt32x4Zero);
+    } else {
+      HValue* size = Add<HConstant>(Int32x4::kSize);
+      filler = Add<HAllocate>(size, HType::Tagged(), NOT_TENURED,
+          Int32x4::kInstanceType);
+      AddStoreMapConstant(filler, isolate()->factory()->int32x4_map());
+      HValue* zero = Add<HConstant>(static_cast<double>(0.0));
+      Add<HStoreNamedField>(filler, HObjectAccess::ForSIMD128XYLanes(), zero);
+      Add<HStoreNamedField>(filler, HObjectAccess::ForSIMD128ZWLanes(), zero);
+    }
+  }
 
   {
     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
index 868d9a5..a7f7b6e 100644 (file)
@@ -2395,6 +2395,9 @@ void LCodeGen::DoBranch(LBranch* instr) {
     __ xorps(xmm_scratch, xmm_scratch);
     __ ucomisd(reg, xmm_scratch);
     EmitBranch(instr, not_equal);
+  } else if (r.IsSIMD128()) {
+    ASSERT(!info()->IsStub());
+    EmitBranch(instr, no_condition);
   } else {
     ASSERT(r.IsTagged());
     Register reg = ToRegister(instr->value());
@@ -2410,6 +2413,9 @@ void LCodeGen::DoBranch(LBranch* instr) {
     } else if (type.IsJSArray()) {
       ASSERT(!info()->IsStub());
       EmitBranch(instr, no_condition);
+    } else if (type.IsSIMD128()) {
+      ASSERT(!info()->IsStub());
+      EmitBranch(instr, no_condition);
     } else if (type.IsHeapNumber()) {
       ASSERT(!info()->IsStub());
       CpuFeatureScope scope(masm(), SSE2);
@@ -2492,6 +2498,18 @@ void LCodeGen::DoBranch(LBranch* instr) {
         __ j(equal, instr->TrueLabel(chunk_));
       }
 
+      if (expected.Contains(ToBooleanStub::FLOAT32x4)) {
+        // Float32x4 value -> true.
+        __ CmpInstanceType(map, FLOAT32x4_TYPE);
+        __ j(equal, instr->TrueLabel(chunk_));
+      }
+
+      if (expected.Contains(ToBooleanStub::INT32x4)) {
+        // Int32x4 value -> true.
+        __ CmpInstanceType(map, INT32x4_TYPE);
+        __ j(equal, instr->TrueLabel(chunk_));
+      }
+
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
         // heap number -> false iff +0, -0, or NaN.
         Label not_heap_number;
index d6b4a7d..0cd6790 100644 (file)
@@ -1028,7 +1028,8 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
   if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
 
   bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
-      type.IsJSArray() || type.IsHeapNumber() || type.IsString();
+      type.IsJSArray() || type.IsHeapNumber() || type.IsSIMD128() ||
+      type.IsString();
   LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() : NULL;
   LInstruction* branch = new(zone()) LBranch(UseRegister(value), temp);
   if (!easy_case &&
index 942170c..4d14299 100644 (file)
@@ -43,6 +43,9 @@
 #include "string-stream.h"
 #include "vm-state-inl.h"
 
+// XDK support
+#include "third_party/xdk/xdk-v8.h"
+
 namespace v8 {
 namespace internal {
 
@@ -160,6 +163,15 @@ class CodeEventLogger::NameBuffer {
     }
   }
 
+  // XDK needs this function temporarily. It will be removed later.
+  void AppendAddress(Address address) {
+    Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
+    int size = OS::SNPrintF(buffer, "0x%x", address);
+    if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
+      utf8_pos_ += size;
+    }
+  }
+
   const char* get() { return utf8_buffer_; }
   int size() const { return utf8_pos_; }
 
@@ -656,6 +668,226 @@ class JitLogger : public CodeEventLogger {
   void* StartCodePosInfoEvent();
   void EndCodePosInfoEvent(Code* code, void* jit_handler_data);
 
+
+  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+  // XDK needs all this stuff below to generate the strings like
+  // "code-creation:..." in the same format as Logger generates.
+  // This string is sent to XDK by code_event_handler and then used for
+  // postprocessing. All these CodeCreateEvent(...) functions and helpers
+  // will be removed before commit.
+  void AppendCodeCreateHeader(NameBuffer* msg,
+                              Logger::LogEventsAndTags tag,
+                              Code* code) {
+    CHECK(msg);
+    msg->AppendBytes(kLogEventsNames[Logger::CODE_CREATION_EVENT]);
+    msg->AppendByte(',');
+    msg->AppendBytes(kLogEventsNames[tag]);
+    msg->AppendByte(',');
+    msg->AppendInt(code->kind());
+    msg->AppendByte(',');
+    msg->AppendAddress(code->instruction_start());
+    msg->AppendByte(',');
+    msg->AppendInt(code->instruction_size());
+    msg->AppendByte(',');
+  }
+
+
+  void AppendDetailed(NameBuffer* msg, String* str, bool show_impl_info) {
+    CHECK(msg);
+    if (str == NULL) return;
+    DisallowHeapAllocation no_gc;  // Ensure string stay valid.
+    int len = str->length();
+    if (len > 0x1000)
+      len = 0x1000;
+    if (show_impl_info) {
+      msg->AppendByte(str->IsOneByteRepresentation() ? 'a' : '2');
+      if (StringShape(str).IsExternal())
+        msg->AppendByte('e');
+      if (StringShape(str).IsInternalized())
+        msg->AppendByte('#');
+      msg->AppendByte(':');
+      msg->AppendInt(str->length());
+      msg->AppendByte(':');
+    }
+    for (int i = 0; i < len; i++) {
+      uc32 c = str->Get(i);
+      if (c > 0xff) {
+        msg->AppendBytes("\\u");
+        msg->AppendHex(c);
+      } else if (c < 32 || c > 126) {
+        msg->AppendBytes("\\x");
+        msg->AppendHex(c);
+      } else if (c == ',') {
+        msg->AppendBytes("\\,");
+      } else if (c == '\\') {
+        msg->AppendBytes("\\\\");
+      } else if (c == '\"') {
+        msg->AppendBytes("\"\"");
+      } else {
+        msg->AppendByte(c);
+      }
+    }
+  }
+
+
+  void AppendDoubleQuotedString(NameBuffer* msg, const char* string) {
+    CHECK(msg);
+    msg->AppendByte('"');
+    for (const char* p = string; *p != '\0'; p++) {
+      if (*p == '"') {
+        msg->AppendByte('\\');
+     }
+      msg->AppendByte(*p);
+    }
+    msg->AppendByte('"');
+  }
+
+
+  void AppendSymbolName(NameBuffer* msg, Symbol* symbol) {
+    CHECK(msg);
+    ASSERT(symbol);
+    msg->AppendBytes("symbol(");
+    if (!symbol->name()->IsUndefined()) {
+      msg->AppendByte('"');
+      AppendDetailed(msg, String::cast(symbol->name()), false);
+      msg->AppendBytes("\" ");
+    }
+    msg->AppendBytes("hash ");
+    msg->AppendHex(symbol->Hash());
+    msg->AppendByte(')');
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code, const char* comment) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, comment);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    AppendDoubleQuotedString(name_buffer_, comment);
+    LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code, Name* name) {
+    if (!xdk::XDKIsAgentAlive()) {
+       CodeEventLogger::CodeCreateEvent(tag, code, name);
+       return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    if (name->IsString()) {
+      name_buffer_->AppendByte('"');
+      AppendDetailed(name_buffer_, String::cast(name), false);
+      name_buffer_->AppendByte('"');
+    } else {
+      AppendSymbolName(name_buffer_, Symbol::cast(name));
+    }
+    LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code,
+                               SharedFunctionInfo* shared,
+                               CompilationInfo* info,
+                               Name* name) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, shared, info, name);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    if (name->IsString()) {
+      SmartArrayPointer<char> str =
+         String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+      name_buffer_->AppendByte('"');
+      name_buffer_->AppendBytes(str.get());
+      name_buffer_->AppendByte('"');
+    } else {
+      AppendSymbolName(name_buffer_, Symbol::cast(name));
+    }
+    name_buffer_->AppendByte(',');
+    name_buffer_->AppendAddress(shared->address());
+    name_buffer_->AppendByte(',');
+    name_buffer_->AppendBytes(ComputeMarker(code));
+    LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
+  }
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code,
+                               SharedFunctionInfo* shared,
+                               CompilationInfo* info,
+                               Name* source,
+                               int line, int column) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, shared,
+                                       info, source, line, column);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    SmartArrayPointer<char> name =
+        shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    name_buffer_->AppendByte('"');
+    name_buffer_->AppendBytes(name.get());
+    name_buffer_->AppendByte(' ');
+    if (source->IsString()) {
+        SmartArrayPointer<char> sourcestr =
+           String::cast(source)->ToCString(DISALLOW_NULLS,
+                                           ROBUST_STRING_TRAVERSAL);
+        name_buffer_->AppendBytes(sourcestr.get());
+    } else {
+        AppendSymbolName(name_buffer_, Symbol::cast(source));
+    }
+    name_buffer_->AppendByte(':');
+    name_buffer_->AppendInt(line);
+    name_buffer_->AppendByte(':');
+    name_buffer_->AppendInt(column);
+    name_buffer_->AppendBytes("\",");
+    name_buffer_->AppendAddress(shared->address());
+    name_buffer_->AppendByte(',');
+    name_buffer_->AppendBytes(ComputeMarker(code));
+    LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code,
+                               int args_count) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, args_count);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    name_buffer_->AppendBytes("\"args_count: ");
+    name_buffer_->AppendInt(args_count);
+    name_buffer_->AppendByte('"');
+  }
+
+
+  virtual void RegExpCodeCreateEvent(Code* code, String* source) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::RegExpCodeCreateEvent(code, source);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, Logger::REG_EXP_TAG, code);
+    name_buffer_->AppendByte('"');
+    AppendDetailed(name_buffer_, source, false);
+    name_buffer_->AppendByte('"');
+  }
+
  private:
   virtual void LogRecordedBuffer(Code* code,
                                  SharedFunctionInfo* shared,
@@ -1378,8 +1610,13 @@ static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
               kLogEventsNames[Logger::CODE_CREATION_EVENT],
               kLogEventsNames[tag],
               code->kind());
-  msg->AppendAddress(code->address());
-  msg->Append(",%d,", code->ExecutableSize());
+  if (xdk::XDKIsAgentAlive()) {
+    msg->AppendAddress(code->instruction_start());
+    msg->Append(",%d,", code->instruction_size());
+  } else {
+    msg->AppendAddress(code->address());
+    msg->Append(",%d,", code->ExecutableSize());
+  }
 }
 
 
@@ -1625,11 +1862,30 @@ void Logger::MoveEventInternal(LogEventsAndTags event,
                                Address from,
                                Address to) {
   if (!FLAG_log_code || !log_->IsEnabled()) return;
+
+  Code* from_code = NULL;
+  Address to_code = NULL;
+  if (xdk::XDKIsAgentAlive()) {
+    from_code = Code::cast(HeapObject::FromAddress(from));
+    const size_t header_size =
+      from_code->instruction_start() - reinterpret_cast<byte*>(from_code);
+    to_code =
+      reinterpret_cast<byte*>(HeapObject::FromAddress(to)) + header_size;
+  }
+
   Log::MessageBuilder msg(log_);
   msg.Append("%s,", kLogEventsNames[event]);
-  msg.AppendAddress(from);
+  if (xdk::XDKIsAgentAlive()) {
+    msg.AppendAddress(from_code->instruction_start());
+  } else {
+    msg.AppendAddress(from);
+  }
   msg.Append(',');
-  msg.AppendAddress(to);
+  if (xdk::XDKIsAgentAlive()) {
+    msg.AppendAddress(to_code);
+  } else {
+    msg.AppendAddress(to);
+  }
   msg.Append('\n');
   msg.WriteToLogFile();
 }
@@ -1750,6 +2006,15 @@ void Logger::TickEvent(TickSample* sample, bool overflow) {
 }
 
 
+void Logger::XDKResumeProfiler() {
+  if (!log_->IsEnabled()) return;
+  if (profiler_ != NULL) {
+    profiler_->resume();
+    is_logging_ = true;
+  }
+}
+
+
 void Logger::StopProfiler() {
   if (!log_->IsEnabled()) return;
   if (profiler_ != NULL) {
@@ -1888,6 +2153,12 @@ void Logger::LogCodeObject(Object* object) {
 
 
 void Logger::LogCodeObjects() {
+  // Starting from Chromium v34 this function is also called from
+  // V8::Initialize. This causes reading the heap to collect already
+  // compiled methods. For XDK that must be done because XDK profiler
+  // consumes CODE_ADDED events and mantains a map of compiled methods.
+  if (xdk::XDKIsAgentAlive()) return;
+
   Heap* heap = isolate_->heap();
   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                           "Logger::LogCodeObjects");
@@ -1948,6 +2219,12 @@ void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
 
 
 void Logger::LogCompiledFunctions() {
+  // Starting from Chromium v34 this function is also called from
+  // V8::Initialize. This causes reading the heap to collect already
+  // compiled methods. For XDK that must be done because XDK profiler
+  // consumes CODE_ADDED events and mantains a map of compiled methods.
+  if (xdk::XDKIsAgentAlive()) return;
+
   Heap* heap = isolate_->heap();
   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                           "Logger::LogCompiledFunctions");
@@ -2083,10 +2360,19 @@ bool Logger::SetUp(Isolate* isolate) {
     is_logging_ = true;
   }
 
+  xdk::XDKInitializeForV8(isolate);
+
   if (FLAG_prof) {
     profiler_ = new Profiler(isolate);
     is_logging_ = true;
     profiler_->Engage();
+
+    if (xdk::XDKIsAgentAlive()) {
+      // A way to to start profiler in pause mode was removed.
+      // To pause collection of the CPU ticks we need to emulate pause.
+      // This will be removed later once XDK agent will have own sampler.
+      profiler_->pause();
+    }
   }
 
   if (FLAG_log_internal_timer_events || FLAG_prof) timer_.Start();
index c01aca2..0b8c0cf 100644 (file)
@@ -363,6 +363,13 @@ class Logger {
   // When data collection is paused, CPU Tick events are discarded.
   void StopProfiler();
 
+  // Resumes collection of CPU Tick events.
+  void XDKResumeProfiler();
+
+  // XDK agent uses it log code map (list of CodeAdded event
+  // before resume CPU Tick events.
+  Log* XDKGetLog() { return log_; }
+
   void LogExistingFunction(Handle<SharedFunctionInfo> shared,
                            Handle<Code> code);
   // Logs all compiled functions found in the heap.
@@ -531,15 +538,15 @@ class CodeEventLogger : public CodeEventListener {
   virtual void SharedFunctionInfoMoveEvent(Address from, Address to) { }
   virtual void CodeMovingGCEvent() { }
 
- private:
+ protected:
   class NameBuffer;
+  NameBuffer* name_buffer_;
 
+ private:
   virtual void LogRecordedBuffer(Code* code,
                                  SharedFunctionInfo* shared,
                                  const char* name,
                                  int length) = 0;
-
-  NameBuffer* name_buffer_;
 };
 
 
index 3785ea8..d2293da 100644 (file)
@@ -72,17 +72,45 @@ function EQUALS(y) {
         if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
         if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
+        if (IsFloat32x4(y) || IsInt32x4(y)) {
+          return %StringEquals(x, %ToString(y));
+        }
         y = %ToPrimitive(y, NO_HINT);
       }
     } else if (IS_SYMBOL(x)) {
       if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
       return 1; // not equal
+    } else if (IsFloat32x4(x)) {
+      while (true) {
+        if (IsFloat32x4(y) || IsInt32x4(y)) {
+          return (x.x == y.x && x.y == y.y && x.z == y.z && x.w == y.w) ? 0 : 1;
+        }
+        if (IS_STRING(y)) return %StringEquals(%ToString(x), y);
+        if (IS_NUMBER(y)) return 1;  // not equal
+        if (IS_SYMBOL(y)) return 1;  // not equal
+        if (IS_BOOLEAN(y)) return y ? 0 : 1;
+        if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
+        y = %ToPrimitive(y, NO_HINT);
+      }
+    } else if (IsInt32x4(x)) {
+      while (true) {
+        if (IsFloat32x4(y) || IsInt32x4(y)) {
+          return (x.x == y.x && x.y == y.y && x.z == y.z && x.w == y.w) ? 0 : 1;
+        }
+        if (IS_STRING(y)) return %StringEquals(%ToString(x), y);
+        if (IS_NUMBER(y)) return 1;  // not equal
+        if (IS_SYMBOL(y)) return 1;  // not equal
+        if (IS_BOOLEAN(y)) return y ? 0 : 1;
+        if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
+        y = %ToPrimitive(y, NO_HINT);
+      }
     } else if (IS_BOOLEAN(x)) {
       if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
       if (IS_NULL_OR_UNDEFINED(y)) return 1;
       if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y);
       if (IS_STRING(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y));
       if (IS_SYMBOL(y)) return 1;  // not equal
+      if (IsFloat32x4(y) || IsInt32x4(y)) return x ? 0 : 1;
       // y is object.
       x = %ToNumber(x);
       y = %ToPrimitive(y, NO_HINT);
@@ -113,6 +141,18 @@ function STRICT_EQUALS(x) {
     return %NumberEquals(this, x);
   }
 
+  if (IsFloat32x4(this)) {
+    if (!IsFloat32x4(x)) return 1;  // not equal
+    return (this.x == x.x && this.y == x.y &&
+            this.z == x.z && this.w == x.w) ? 0 : 1;
+  }
+
+  if (IsInt32x4(this)) {
+    if (!IsInt32x4(x)) return 1;  // not equal
+    return (this.x == x.x && this.y == x.y &&
+            this.z == x.z && this.w == x.w) ? 0 : 1;
+  }
+
   // If anything else gets here, we just do simple identity check.
   // Objects (including functions), null, undefined and booleans were
   // checked in the CompareStub, so there should be nothing left.
@@ -149,6 +189,20 @@ function COMPARE(x, ncr) {
   right = %ToPrimitive(x, NUMBER_HINT);
   if (IS_STRING(left) && IS_STRING(right)) {
     return %_StringCompare(left, right);
+  } else if ((IsFloat32x4(left)  || IsInt32x4(left)) &&
+             (IsFloat32x4(right) || IsInt32x4(right))) {
+    if ((left.x == right.x) && (left.y == right.y) &&
+        (left.z == right.z) && (left.w == right.w)) {
+      return 0;  // equal
+    }
+    if ((left.x < right.x) && (left.y < right.y) &&
+        (left.z < right.z) && (left.w < right.w)) {
+      return -1;  // less
+    }
+    if ((left.x > right.x) && (left.y > right.y) &&
+        (left.z > right.z) && (left.w > right.w)) {
+      return 1;  // great
+    }
   } else {
     var left_number = %ToNumber(left);
     var right_number = %ToNumber(right);
@@ -525,6 +579,8 @@ function ToNumber(x) {
   if (IS_BOOLEAN(x)) return x ? 1 : 0;
   if (IS_UNDEFINED(x)) return NAN;
   if (IS_SYMBOL(x)) return NAN;
+  if (IsFloat32x4(x)) return NAN;
+  if (IsInt32x4(x)) return NAN;
   return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
 }
 
@@ -536,8 +592,8 @@ function NonNumberToNumber(x) {
   if (IS_BOOLEAN(x)) return x ? 1 : 0;
   if (IS_UNDEFINED(x)) return NAN;
   if (IS_SYMBOL(x)) return NAN;
-  if (IsFloat32x4(x)) return NaN;
-  if (IsInt32x4(x)) return NaN;
+  if (IsFloat32x4(x)) return NAN;
+  if (IsInt32x4(x)) return NAN;
   return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
 }
 
@@ -572,6 +628,8 @@ function ToObject(x) {
   if (IS_STRING(x)) return new $String(x);
   if (IS_NUMBER(x)) return new $Number(x);
   if (IS_BOOLEAN(x)) return new $Boolean(x);
+  if (IsFloat32x4(x)) return new $Float32x4(x.x, x.y, x.z, x.w);
+  if (IsInt32x4(x)) return new $Int32x4(x.x, x.y, x.z, x.w);
   if (IS_SYMBOL(x)) return %NewSymbolWrapper(x);
   if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
     throw %MakeTypeError('undefined_or_null_to_object', []);
diff --git a/src/v8/src/third_party/xdk/xdk-agent.cc b/src/v8/src/third_party/xdk/xdk-agent.cc
new file mode 100644 (file)
index 0000000..3cec7e8
--- /dev/null
@@ -0,0 +1,451 @@
+// Copyright (c) 2013 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.
+
+#ifdef __linux__
+#include <sys/stat.h>
+#endif  // __linux__
+
+#include "xdk-agent.h"
+#include <vector>
+#include <string>
+#include <sstream>
+#include "platform.h"
+#include "log-utils.h"
+
+namespace xdk {
+namespace internal {
+
+static unsigned int XDK_COMMAND_LENGTH = 100;  // It should be enough.
+
+static const char* XDK_TRACE_FILE =
+  "/data/data/com.intel.app_analyzer/files/result.xdk2v8";
+
+static const char* XDK_MARKER_FILE =
+  "/data/data/com.intel.app_analyzer/files/profiler.run";
+
+XDKAgent XDKAgent::instance_;
+
+// SetIdle has the same semantics as CpuProfiler::SetIdle has (v8/src/api.cc)
+// It is used to tell the sampler that XDK agent is idle (it is not busy with
+// some tasks). If the agent is idle that the sampler put a IDLE VM state into
+// the Tick record. The samples happen during IDLE will be attributed to (idle)
+// line in the XDK viewer.
+static void SetIdle(bool isIdle, v8engine::Isolate* isolate) {
+  CHECK(isolate);
+  v8engine::StateTag state = isolate->current_vm_state();
+  if (isolate->js_entry_sp() != NULL) return;
+  if (state == v8engine::EXTERNAL || state == v8engine::IDLE) {
+    if (isIdle) {
+      isolate->set_current_vm_state(v8engine::IDLE);
+    } else if (state == v8engine::IDLE) {
+      isolate->set_current_vm_state(v8engine::EXTERNAL);
+    }
+  }
+}
+
+
+bool XDKAgent::setUp(v8engine::Isolate* isolate) {
+  CHECK(isolate);
+
+  if (m_isolate) {
+    // The setUp method is called for the main thread first, then may be called
+    // again if the app uses Workers (each Worker object has own V8 instance).
+    // XDK agent does not support JavaScript Worker currently.
+    XDKLog("xdk: Agent is already initialized\n");
+    return false;
+  }
+
+  FILE* file = v8engine::OS::FOpen(XDK_MARKER_FILE, "r");
+  if (file == NULL) {
+    return false;
+  }
+
+  fclose(file);
+  m_alive = true;
+  m_isolate = isolate;
+
+  return m_alive;
+}
+
+
+void XDKAgent::resumeSampling() {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  CHECK(m_isolate);
+
+  v8engine::Log* log = m_isolate->logger()->XDKGetLog();
+  CHECK(log);
+
+  // Create a new log file for new profiling session
+  CHECK(!log->IsEnabled());
+  log->Initialize(XDK_TRACE_FILE);
+
+#ifdef __linux__
+  int mode = S_IRUSR|S_IROTH|S_IRGRP|S_IWUSR|S_IWOTH|S_IWGRP;
+  if (chmod(XDK_TRACE_FILE, mode) != 0) {
+    XDKLog("xdk: Couldn't change permissions for a trace file\n");
+  }
+#endif  // __linux__
+
+  CHECK(log->IsEnabled());
+
+  logFunctionSnapshot();
+
+  // Write a marker line into the log for testing purpose
+  v8engine::Log::MessageBuilder msg(log);
+  msg.Append("Profiler started.\n");
+  msg.WriteToLogFile();
+
+  // Resume collection the CPU Tick events
+  m_isolate->logger()->XDKResumeProfiler();
+  XDKLog("xdk: Sampling is resumed\n");
+
+  SetIdle(true, m_isolate);
+}
+
+
+void XDKAgent::pauseSampling() {
+  // Pause collection the CPU Tick events
+  CHECK(m_isolate);
+  m_isolate->logger()->StopProfiler();
+
+  // Use v8 logger internals to close the trace file.
+  // Once XDK agent implements own sampler this will be removed.
+  v8engine::Log* log = m_isolate->logger()->XDKGetLog();
+  CHECK(log);
+  log->stop();
+  log->Close();
+
+  XDKLog("xdk: Sampling is stopped\n");
+}
+
+
+struct ObjectDeallocator {
+  template<typename T>
+  void operator()(const T& obj) const { delete obj.second; }
+};
+
+
+XDKAgent::~XDKAgent() {
+  CHECK(m_server != NULL);
+  CHECK(m_agent_access != NULL);
+
+  if (m_alive) {
+    CHECK(m_isolate != NULL);
+
+    m_terminate = true;
+
+    std::for_each(m_lineMaps.begin(), m_lineMaps.end(), ObjectDeallocator());
+    m_lineMaps.clear();
+
+    m_server->Shutdown();
+
+    Join();
+  }
+
+  delete m_server;
+  m_server = NULL;
+
+  delete m_agent_access;
+  m_agent_access = NULL;
+
+  m_isolate = NULL;
+}
+
+
+// The XDK listener thread.
+void XDKAgent::Run() {
+  v8engine::Isolate::EnsureDefaultIsolate();
+  v8engine::DisallowHeapAllocation no_allocation;
+  v8engine::DisallowHandleAllocation no_handles;
+  v8engine::DisallowHandleDereference no_deref;
+
+  XDKLog("xdk: Listener thread is running\n");
+  CHECK(m_server);
+
+  bool ok = m_server->Bind(m_port);
+  if (!ok) {
+    XDKLog("xdk: Unable to bind port=%d %d\n",
+            m_port, v8engine::Socket::GetLastError());
+    return;
+  }
+
+  std::vector<char> buf(XDK_COMMAND_LENGTH);
+
+  const std::string cmdStart = "start";
+  const std::string cmdStop = "stop";
+
+  while (!m_terminate) {
+    XDKLog("xdk: Listener thread is waiting for connection\n");
+
+    ok = m_server->Listen(1);
+    XDKLog("xdk: Listener thread got a connection request. Return value=%d\n",
+             v8engine::Socket::GetLastError());
+    if (ok) {
+      v8engine::Socket* client = m_server->Accept();
+      if (client == NULL) {
+        XDKLog("xdk: Accept failed %d\n", v8engine::Socket::GetLastError());
+        continue;
+      }
+
+      XDKLog("xdk: Connected\n");
+
+      int bytes_read = client->Receive(&buf[0], buf.size() - 1);
+      if (bytes_read == 0) {
+        XDKLog("xdk: Receive failed %d\n", v8engine::Socket::GetLastError());
+        break;
+      }
+      buf[bytes_read] = '\0';
+
+  #ifdef WIN32
+      if (bytes_read > 3) buf[bytes_read - 2] = '\0';  // remove CR+LF symbols
+  #else
+      if (bytes_read > 2) buf[bytes_read - 1] = '\0';  // remove LF symbol
+  #endif
+
+      std::string clientCommand(&buf[0]);
+      XDKLog("xdk: Got '%s' profiling command\n", clientCommand.c_str());
+
+      if (clientCommand == cmdStart) {
+        resumeSampling();
+      } else if (clientCommand == cmdStop) {
+        pauseSampling();
+      } else {
+        XDKLog("xdk: '%s' is not handled command\n", clientCommand.c_str());
+        break;
+      }
+    }
+  }
+
+  XDKLog("xdk: Listener thread is stopped\n");
+  return;
+}
+
+
+void XDKAgent::processCodeMovedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  v8engine::Address from = static_cast<v8engine::Address>(event->code_start);
+  v8engine::Address to = static_cast<v8engine::Address>(event->new_code_start);
+
+  if (!from || !to) return;
+  XDKLog("xdk: CODE_MOVED from=0x%x to=0x%x\n", from, to);
+  m_snapshot.move(from, to);
+}
+
+
+void XDKAgent::processCodeRemovedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  v8engine::Address addr = static_cast<v8engine::Address>(event->code_start);
+
+  if (!addr) return;
+  XDKLog("xdk: CODE_REMOVED for addr=0x%x\n", addr);
+  m_snapshot.remove(addr);
+}
+
+
+void XDKAgent::processCodeAddedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+
+  v8engine::Address codeAddr =
+    static_cast<v8engine::Address>(event->code_start);
+  uint32_t codeLen = event->code_len;
+
+  if (!codeAddr || !codeLen) return;
+  XDKLog("xdk: CODE_ADDED for addr=0x%x len=0x%x\n", codeAddr, codeLen);
+
+  // Look for line number information
+  LineMap* lineMap = NULL;
+  LineMaps::iterator itr = m_lineMaps.find(codeAddr);
+  if (itr == m_lineMaps.end()) {
+    XDKLog("xdk: Unable to find line info for addr=0x%x\n", codeAddr);
+  } else {
+    lineMap = itr->second;
+
+    // Remove line map if no chance to get source lines for it
+    v8::Handle<v8::Script> script = event->script;
+    if (*script != NULL && *(script->GetUnboundScript()) != NULL) {
+      // Convert V8 pos value into source line number.
+      LineMap::Entries* entries =
+        const_cast<LineMap::Entries*>(lineMap->getEntries());
+      CHECK(entries);
+      CHECK(entries->size());
+      XDKLog("xdk: Found line info (%d lines) for addr=0x%x\n",
+              entries->size(), codeAddr);
+      size_t srcLine = 0;
+      LineMap::Entries::iterator lineItr = entries->begin();
+      LineMap::Entries::iterator lineEnd = entries->end();
+      for (; lineItr != lineEnd; ++lineItr) {
+        srcLine = script->GetUnboundScript()->GetLineNumber(lineItr->line) + 1;
+        lineItr->line = srcLine;
+        XDKLog("xdk:   offset=%p line=%d\n", lineItr->pcOffset, lineItr->line);
+      }
+    } else {
+      XDKLog("xdk: Script is empty. No line info for addr=0x%x.\n", codeAddr);
+      delete lineMap;
+      lineMap = NULL;
+      m_lineMaps.erase(codeAddr);
+    }
+  }
+
+  std::string funcType;
+  std::string name(event->name.str, event->name.len);
+  Function func(codeAddr, codeLen, name, funcType, lineMap);
+
+  if (lineMap) {
+    // Put the line number information for the given method into the trace file
+    // if profiling session is running.
+    logLineNumberInfo(codeAddr, *lineMap);
+
+    // Release memory allocated on CODE_START_LINE_INFO_RECORDING
+    delete lineMap;
+    lineMap = NULL;
+    m_lineMaps.erase(codeAddr);
+  }
+
+  m_snapshot.insert(func);
+}
+
+
+void XDKAgent::processLineMapAddedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  v8engine::Address codeAddr =
+    static_cast<v8engine::Address>(event->code_start);
+  void* userData = event->user_data;
+
+  if (!userData || !codeAddr) return;
+
+  LineMap* lineMap = reinterpret_cast<LineMap*>(userData);
+  if (lineMap->getSize() == 0) {
+    XDKLog("xdk: CODE_END_LINE no entries for user_data=%p addr=0x%x\n",
+            userData, codeAddr);
+    return;
+  }
+
+  std::pair<LineMaps::iterator, bool>
+    result = m_lineMaps.insert(std::make_pair(codeAddr, lineMap));
+  if (!result.second) {
+    m_lineMaps.erase(codeAddr);
+    XDKLog("xdk: removed unprocessed line info for addr=0x%x\n", codeAddr);
+    result = m_lineMaps.insert(std::make_pair(codeAddr, lineMap));
+    CHECK(result.second);
+  }
+
+  XDKLog("xdk: CODE_END_LINE added %d entries for user_data=%p addr=0x%x\n",
+           lineMap->getSize(), userData, codeAddr);
+}
+
+
+void EventHandler(const v8::JitCodeEvent* event) {
+  // This callback is called regardless of whether profiling is running.
+  //
+  // By default profiling is launched in paused mode, the agent is awaiting
+  // a command to resume profiling. At the same time, V8's JIT compiler is
+  // working. The functions which are JIT-compiled while sampling is paused
+  // are cached by V8's Logger and will be written in log (trace file) when
+  // XDK resumes the profiling. The line number info for such functions are not
+  // cached. We need to capture and cache the line number info and flush
+  // the cache on resume profiling.
+
+  if (event == NULL) return;
+
+  switch (event->type) {
+    case v8::JitCodeEvent::CODE_MOVED:
+      XDKAgent::instance().processCodeMovedEvent(event);
+      break;
+
+    case v8::JitCodeEvent::CODE_REMOVED:
+      XDKAgent::instance().processCodeRemovedEvent(event);
+      break;
+
+    case v8::JitCodeEvent::CODE_ADDED:
+      XDKAgent::instance().processCodeAddedEvent(event);
+
+    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
+      void* userData = event->user_data;
+      if (!userData) return;
+      LineMap* lineMap = reinterpret_cast<LineMap*>(userData);
+      size_t offset = event->line_info.offset;
+      size_t pos = event->line_info.pos;
+      lineMap->setPosition(offset, pos);
+      XDKLog("xdk: CODE_ADD_LINE_POS for user_data=%p offset=0x%x pos=%d\n",
+               userData, offset, pos);
+      break;
+    }
+
+    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
+      v8::JitCodeEvent* data = const_cast<v8::JitCodeEvent*>(event);
+      data->user_data = new LineMap();
+      XDKLog("xdk: CODE_START_LINE for user_data=%p\n", event->user_data);
+      break;
+    }
+
+    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
+      XDKAgent::instance().processLineMapAddedEvent(event);
+      break;
+    }
+
+    default:
+      XDKLog("xdk: Unknown event\n");
+      break;
+  }
+
+  SetIdle(true, XDKAgent::instance().isolate());
+
+  return;
+}
+
+
+void XDKAgent::logLineNumberInfo(v8engine::Address addr,
+                                 const LineMap& lineInfo) {
+  CHECK(addr);
+  v8engine::Log* log = m_isolate->logger()->XDKGetLog();
+  CHECK(log);
+  if (!log->IsEnabled()) return;
+  if (lineInfo.getSize() == 0) return;
+  const LineMap::Entries* lines = lineInfo.getEntries();
+  CHECK(lines);
+  LineMap::Entries::const_iterator lineItr = lines->begin();
+  LineMap::Entries::const_iterator lineEnd = lines->end();
+
+  // Put 'src-pos' lines into the log in our own format
+  for (; lineItr != lineEnd; ++lineItr) {
+    v8engine::Log::MessageBuilder msg(m_isolate->logger()->XDKGetLog());
+    msg.Append("src-pos,");
+    msg.Append("0x%x,%d,%d\n", addr, lineItr->pcOffset, lineItr->line);
+    msg.WriteToLogFile();
+  }
+}
+
+
+void XDKAgent::logFunctionSnapshot() {
+  CHECK(m_isolate);
+
+  CodeMap::const_iterator funcItr = m_snapshot.entries().begin();
+  CodeMap::const_iterator funcEnd = m_snapshot.entries().end();
+
+  XDKLog("FunctionSnapshot: %d entries\n", m_snapshot.entries().size());
+  if (m_snapshot.entries().size() == 0) return;
+
+  unsigned int i = 1;
+
+  for (; funcItr != funcEnd; ++funcItr, i++) {
+    const Range& range = funcItr->first;
+    const Function& func = funcItr->second;
+
+    XDKLog("%d    %s\n", i, func.getLogLine().c_str());
+
+    const LineMap& map = func.getLineMap();
+    if (map.getSize()) {
+      v8engine::Address codeAddr = range.start();
+      XDKLog("  Found %d lines for addr=%p\n", map.getSize(), codeAddr);
+      logLineNumberInfo(codeAddr, map);
+    }
+
+    // Write 'code-creation' line into the log
+    v8engine::Log::MessageBuilder msg(m_isolate->logger()->XDKGetLog());
+    msg.Append("%s\n", func.getLogLine().c_str());
+    msg.WriteToLogFile();
+  }
+}
+
+}}  // namespace xdk::internal
diff --git a/src/v8/src/third_party/xdk/xdk-agent.h b/src/v8/src/third_party/xdk/xdk-agent.h
new file mode 100644 (file)
index 0000000..183f514
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright (c) 2013 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 XDK_AGENT_H_
+#define XDK_AGENT_H_
+
+#include "v8.h"
+#include "sampler.h"
+#include "platform.h"
+#include "platform/socket.h"
+#include "platform/mutex.h"
+#include "xdk-types.h"
+#include "xdk-code-map.h"
+
+// ----------------------------------------------------------------------------
+//
+// This file declares XDKAgent class which does
+//
+// - Handles the code events to maintain the code map.
+// - Handles the line info events to assosiate the line info with code event.
+// - Accepts start / stop profiling commands from AppAnalyzer.
+//
+// ----------------------------------------------------------------------------
+
+namespace xdk {
+namespace internal {
+
+const int XDK_AGENT_PORT = 48899;
+
+// Callback called by V8 builtin logger.
+void EventHandler(const v8::JitCodeEvent* event);
+
+// XDK profiling agent. It starts a socket listener on the specific port and
+// handles commands to start and stop sampling.
+class XDKAgent : public v8engine::Thread {
+ public:
+  static XDKAgent& instance() {
+    return instance_;
+  }
+
+  void Run();
+
+  bool setUp(v8engine::Isolate* isolate);
+  bool isAlive() const { return m_alive; }
+
+  void processCodeMovedEvent(const v8::JitCodeEvent* event);
+  void processCodeRemovedEvent(const v8::JitCodeEvent* event);
+  void processCodeAddedEvent(const v8::JitCodeEvent* event);
+  void processLineMapAddedEvent(const v8::JitCodeEvent* event);
+
+  inline v8engine::Isolate* isolate() { return m_isolate; }
+
+ private:
+  virtual ~XDKAgent();
+  XDKAgent()
+      : v8engine::Thread("xdk:agent"),
+        m_alive(false),
+        m_port(XDK_AGENT_PORT),
+        m_server(new v8engine::Socket()),
+        m_agent_access(new v8engine::Mutex()),
+        m_isolate(NULL),
+        m_terminate(false) {
+    CHECK(m_server != NULL);
+    CHECK(m_agent_access != NULL);
+  }
+  XDKAgent(const XDKAgent&);
+  XDKAgent& operator=(const XDKAgent&);
+
+  void logFunctionSnapshot();
+  void logLineNumberInfo(v8engine::Address codeAddr, const LineMap& lineInfo);
+
+  void resumeSampling();
+  void pauseSampling();
+
+  bool m_alive;
+
+  const int m_port;  // Port to use for the agent.
+  v8engine::Socket* m_server;  // Server socket for listen/accept.
+  v8engine::Mutex* m_agent_access;
+  v8engine::Isolate* m_isolate;
+
+  // The snapshot of compiled methods at present moment.
+  FunctionSnapshot m_snapshot;
+
+  // The processLineMapAddedEvent function adds a new map for code starting
+  // address. Newly added map describes how ps offsets maps to internal pos,
+  // but not how ps offsets maps to line number within source file.
+  //
+  // On CodeAdd event, processCodeAddedEvent function looks for line map for
+  // a code address. If map is found that assign it to a object of Function type
+  // in FunctionSnapshot. Before assign the pc offset to pos map is converted
+  // to pc offset to source line.
+  //
+  // CodeMoved and CodeRemoved must not affect this map.
+  // Current understanding of V8 code generator: V8 first emits LineStart event,
+  // then bunch of LineAdd events, then LineEnd event, finally CodeAdded event.
+  // Based on above no need to add any 'smart' logic on CodeMoved and
+  // CodeRemoved for line map.
+  //
+  // Basically it should be always empty.
+  LineMaps m_lineMaps;
+
+  bool m_terminate;  // Termination flag for listening thread.
+
+  static XDKAgent instance_;
+};
+
+} }  // namespace xdk::internal
+
+#endif  // XDK_AGENT_H_
diff --git a/src/v8/src/third_party/xdk/xdk-code-map.cc b/src/v8/src/third_party/xdk/xdk-code-map.cc
new file mode 100644 (file)
index 0000000..2f25c4c
--- /dev/null
@@ -0,0 +1,145 @@
+// Copyright (c) 2013 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 "xdk-code-map.h"
+#include <sstream>
+
+namespace xdk {
+namespace internal {
+
+static std::string replaceAddress(const std::string& str,
+                                  v8engine::Address addr) {
+  // The input str: code-creation,LazyCompile,0,0x3851c4e0,200," native uri.js"
+  std::string first;
+  std::string end;
+
+  std::size_t found = str.find(',');
+  if (found != std::string::npos) {
+    found = str.find(',', found + 1);
+    if (found != std::string::npos) {
+      found = str.find(',', found + 1);
+      if (found != std::string::npos) {
+        first = str.substr(0, found);
+        found = str.find(',', found + 1);
+        if (found != std::string::npos) {
+          end = str.substr(found, str.size() - found);
+        }
+      }
+    }
+  }
+
+  if (!first.size() || !end.size()) return str;
+
+  std::stringstream ss;
+  ss << first << ','
+     << std::showbase << std::hex << static_cast<void*>(addr) << end;
+  return ss.str();
+}
+
+
+Function::Function(v8engine::Address codeAddr, uint32_t codeLen,
+                   const std::string& name, const std::string& type,
+                   const LineMap* lineMap)
+    : m_codeAddr(codeAddr), m_codeLen(codeLen), m_name(name), m_type(type) {
+  CHECK(codeAddr);
+  CHECK(codeLen);
+  // Can't be empty because it's came from CodeCreation(...) events
+  CHECK(!name.empty());
+  m_logLine = m_name;
+
+  if (lineMap && lineMap->getSize()) m_lineMap = *lineMap;
+}
+
+
+void FunctionSnapshot::removeAll(const Range& range) {
+  CodeMap::iterator low = m_impl.lower_bound(range);
+  CodeMap::iterator up = m_impl.upper_bound(range);
+  CodeMap::iterator::difference_type num = std::distance(low, up);
+
+  if (num) {
+    XDKLog("xdk: %d ranges were overlapped and removed\n", num);
+
+    CodeMap::iterator itr = low;
+    for (; itr != up; ++itr) {
+      XDKLog("xdk:  ovrl&removed addr=0x%x len=0x%x name=%s\n",
+             itr->first.start(), itr->first.length(),
+             itr->second.getLogLine().c_str());
+    }
+    m_impl.erase(low, up);
+  }
+}
+
+
+void FunctionSnapshot::insert(const Function& func) {
+  v8engine::Address codeAddr = func.getCodeAddress();
+  uint32_t codeLen = func.getCodeLength();
+  CHECK(codeAddr);
+  CHECK(codeLen);
+
+  Range range(codeAddr, codeLen);
+
+  removeAll(range);
+
+  std::pair<CodeMap::iterator, bool> res =
+    m_impl.insert(std::make_pair(range, func));
+  CHECK(res.second);
+
+  XDKLog("xdk: size=%d added addr=0x%x name=%s\n",
+         m_impl.size(), range.start(), func.getLogLine().c_str());
+}
+
+
+void FunctionSnapshot::remove(v8engine::Address codeAddr) {
+  if (!codeAddr) return;
+  CodeMap::iterator itr = m_impl.find(Range(codeAddr, 1));
+  if (itr != m_impl.end()) {
+    std::string name = itr->second.getLogLine();
+    uint32_t len = itr->first.length();
+    m_impl.erase(itr);
+    XDKLog("xdk: size=%d removed addr=0x%x name=%s\n",
+           m_impl.size(), codeAddr, len, name.c_str());
+  }
+}
+
+
+void FunctionSnapshot::move(v8engine::Address from, v8engine::Address to) {
+  if (!from || !to) return;
+  if (from == to) return;
+
+  CodeMap::iterator itr = m_impl.find(Range(from, 1));
+  if (itr == m_impl.end()) {
+    XDKLog("xdk: couldn't find a code to move from=0x%x to=0x%x\n", from, to);
+    return;
+  }
+  if (itr->first.start() != from) {
+    XDKLog("xdk: discarded move from=0x%x to=0x%x\n", from, to);
+    return;
+  }
+
+  uint32_t codeLen = itr->second.getCodeLength();
+  const LineMap& lines = itr->second.getLineMap();
+
+  // In case of CodeMoved we have to check that name contains the same code
+  // addr and code length as the input params and replace if they are different.
+  const std::string& orig = itr->second.getName();
+  std::string name = replaceAddress(orig, to);
+
+  const std::string& type = itr->second.getType();
+  Function toEntry(to, codeLen, name, type, &lines);
+
+  m_impl.erase(itr);
+
+  Range range(to, codeLen);
+  removeAll(range);
+
+  // Now ready to move
+
+  bool ok = m_impl.insert(std::make_pair(range, toEntry)).second;
+  CHECK(ok);
+
+  XDKLog("xdk: size=%d moved from=0x%x to=0x%x name=%s\n",
+         m_impl.size(), from, to, toEntry.getLogLine().c_str());
+}
+
+} }  // namespace xdk::internal
diff --git a/src/v8/src/third_party/xdk/xdk-code-map.h b/src/v8/src/third_party/xdk/xdk-code-map.h
new file mode 100644 (file)
index 0000000..18e3c09
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright (c) 2013 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 XDK_CODE_MAP_H_
+#define XDK_CODE_MAP_H_
+
+// ----------------------------------------------------------------------------
+//
+// This file contains the FunctionSnapshot and related objects declarations
+//
+// The FunctionSnapshot object maintains a map of JIT compiled functions.
+// It is modified on code events(CodeAdded, CodeMoved and CodeDeleted) from
+// V8 built-in profiler.
+//
+// ----------------------------------------------------------------------------
+
+#include "xdk-types.h"
+#include <map>
+#include <list>
+#include <string>
+#include <algorithm>
+
+namespace xdk {
+namespace internal {
+
+class LineMap;
+typedef std::map<
+          v8engine::Address,  // start address of code
+          LineMap*> LineMaps;
+
+// This class is used to record the JITted code position info for JIT
+// code profiling.
+class LineMap {
+ public:
+  struct LineEntry {
+    LineEntry(size_t offset, size_t line)
+      : pcOffset(offset), line(line) { }
+
+    size_t pcOffset;  // PC offset from the begining of the code trace.
+    size_t line;      // Can be either position returned from V8 assembler
+                      // (which needs to be converted to src line) or src line
+                      // number.
+  };
+
+  typedef std::list<LineEntry> Entries;
+
+  void setPosition(size_t offset, size_t line) {
+    addCodeLineEntry(LineEntry(offset, line));
+  }
+
+  inline size_t getSize() const { return m_lines.size(); }
+  const Entries* getEntries() const { return &m_lines; }
+
+ private:
+  void addCodeLineEntry(const LineEntry& entry) { m_lines.push_back(entry); }
+
+  Entries m_lines;
+};
+
+// This class describes the function reported with CodeAdded event.
+class Function {
+ public:
+  explicit Function(v8engine::Address codeAddr, uint32_t codeLen,
+                    const std::string& name, const std::string& type,
+                    const LineMap* lineMap);
+
+  inline v8engine::Address getCodeAddress() const { return m_codeAddr; }
+  inline uint32_t getCodeLength() const { return m_codeLen; }
+
+  inline const std::string& getType() const { return m_type; }
+  inline const std::string& getName() const { return m_name; }
+  inline const std::string& getLogLine() const { return m_logLine; }
+
+  const LineMap& getLineMap() const { return m_lineMap; }
+
+ private:
+  v8engine::Address m_codeAddr;
+  uint32_t m_codeLen;
+  std::string m_name;
+  std::string m_type;
+  std::string m_logLine;
+  LineMap m_lineMap;
+};
+
+// This class describes the code range related to object of Function type.
+// The start address and length are taken from CodeAdded event.
+class Range {
+ public:
+  class Comparator : public std::binary_function<Range&, Range&, bool> {
+   public:
+     bool operator()(const Range& l, const Range& r) const {
+       return (l.start() + l.length() <= r.start());
+     }
+  };
+
+  Range(v8engine::Address start, uint32_t length)
+    : m_start(start), m_length(length) { }
+
+  inline v8engine::Address start() const { return m_start; }
+  inline uint32_t length() const { return m_length; }
+
+ private:
+  v8engine::Address m_start;
+  uint32_t m_length;
+};
+
+// This class maintains a map of JIT compiled functions.
+// The content is changed on CodeAdded, CodeMoved and CodeDeleted events.
+typedef std::map<Range, const Function, Range::Comparator> CodeMap;
+
+class FunctionSnapshot {
+ public:
+  explicit FunctionSnapshot() {}
+  virtual ~FunctionSnapshot() { m_impl.clear(); }
+
+  void insert(const Function& func);
+  void move(v8engine::Address from, v8engine::Address to);
+  void remove(v8engine::Address addr);
+
+  inline const CodeMap& entries() { return m_impl; }
+
+ private:
+  FunctionSnapshot(const FunctionSnapshot&);
+  FunctionSnapshot& operator=(const FunctionSnapshot&);
+
+  void removeAll(const Range& range);
+
+  CodeMap m_impl;
+};
+
+} }  // namespace xdk::internal
+
+#endif  // XDK_CODE_MAP_H_
diff --git a/src/v8/src/third_party/xdk/xdk-types.h b/src/v8/src/third_party/xdk/xdk-types.h
new file mode 100644 (file)
index 0000000..4fc9fd0
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (c) 2013 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 XDK_TYPES_H_
+#define XDK_TYPES_H_
+
+#include "v8.h"
+#include "platform.h"
+
+namespace v8engine = v8::internal;
+
+static void XDKLog(const char* msg, ...) {
+#if DEBUG
+  va_list arguments;
+  va_start(arguments, msg);
+  v8engine::OS::VPrint(msg, arguments);
+  va_end(arguments);
+#endif
+}
+
+#endif  // XDK_TYPES__H_
+
diff --git a/src/v8/src/third_party/xdk/xdk-v8.cc b/src/v8/src/third_party/xdk/xdk-v8.cc
new file mode 100644 (file)
index 0000000..a2ac333
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 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 "../../../include/v8.h"
+#include "xdk-v8.h"
+#include "xdk-agent.h"
+
+namespace xdk {
+
+void XDKInitializeForV8(v8::internal::Isolate* isolate) {
+  if (!internal::XDKAgent::instance().setUp(isolate)) return;
+
+  XDKLog("xdk: XDKInitializeForV8\n");
+
+  // The --prof flag is requred for now to enable the CPU ticks collection.
+  // This flag will be removed once xdk agent implements own sampler.
+  const char* flags = "--prof";
+  v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
+
+  v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault,
+                                 xdk::internal::EventHandler);
+
+  internal::XDKAgent::instance().Start();
+}
+
+
+bool XDKIsAgentAlive() {
+  return internal::XDKAgent::instance().isAlive();
+}
+
+}  // namespace xdk
diff --git a/src/v8/src/third_party/xdk/xdk-v8.gyp b/src/v8/src/third_party/xdk/xdk-v8.gyp
new file mode 100644 (file)
index 0000000..10f3b3b
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (c) 2013 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.
+
+{
+  'variables': {
+    'v8_code': 1,
+   },
+  'includes': ['../../../build/toolchain.gypi', '../../../build/features.gypi'],
+  'targets': [
+    {
+      'target_name': 'v8_xdk',
+      'type': 'static_library',
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ],
+      'include_dirs+': [
+        '../../',
+      ],
+      'sources': [
+        'xdk-v8.h',
+        'xdk-v8.cc',
+        'xdk-agent.h',
+        'xdk-agent.cc',
+        'xdk-code-map.h',
+        'xdk-code-map.cc',
+        'xdk-types.h',
+      ],
+      'direct_dependent_settings': {
+        'conditions': [
+          ['OS != "win"', {
+            'libraries': ['-ldl',],
+          }],
+        ],
+      },
+    },
+  ]
+}
diff --git a/src/v8/src/third_party/xdk/xdk-v8.h b/src/v8/src/third_party/xdk/xdk-v8.h
new file mode 100644 (file)
index 0000000..56e717f
--- /dev/null
@@ -0,0 +1,107 @@
+// Copyright (c) 2013 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 V8_XDK_H_
+#define V8_XDK_H_
+
+// ----------------------------------------------------------------------------
+//
+//                          XDK profiling support for V8
+//
+//  SOURCES:
+//
+//  1. XDK agent source files are located in v8/src/third_party/xdk folder.
+//
+//       To integrate this stuff into V8 build system you need to modify
+//       two v8 files:
+//
+//       1. v8/build/features.gypi
+//           'v8_enable_xdkprof': 1,
+//       2. v8/tools/gyp/v8.gyp
+//           ['v8_enable_xdkprof==1', {
+//             'dependencies': ['../../src/third_party/xdk/xdk-v8.gyp:v8_xdk',],
+//           }],
+//
+//  2. Two V8 files v8/src/log.cc and v8/src/log.h need to be modified
+//
+//       The changes related to start CPU ticks collection using V8 built-in
+//       profiler.
+//       We are working on reduce these changes up to 2 lines:
+//
+//           #include "third_party/xdk/xdk-v8.h"
+//           bool Logger::SetUp(Isolate* isolate) {
+//             ...
+//             xdk::XDKInitializeForV8(isolate);
+//             ...
+//           }
+//
+//  OVERVIEW:
+//
+//  Start up
+//
+//    XDK agent is initialized as a part of V8 built-in profiler on process
+//    start up. V8 built-in profiler should be paused (CPU ticks are not
+//    collected).
+//
+//           v8/src/log.cc:
+//           bool Logger::SetUp(Isolate* isolate) {
+//             ...
+//             xdk::XDKInitializeForV8(isolate);
+//             ...
+//           }
+//
+//      XDKInitializeForV8() function
+//      1. Checks whether XDK agent can be initialized. If a marker file is not
+//         found that initialization will be discarded.
+//      2. Starts a listener thread to accept start / stop profiling command
+//         from AppAnalyzer (xdk/xdk-agent.cc).
+//      3. Registeres a callback to consume the CodeAdded, CodeMoved,
+//         CodeDeleted events and events related to source line info by
+//         the agent.
+//
+//  Runtime
+//
+//    XDK profiler consumes the code events (EventHandler() in xdk/xdk-agent.cc)
+//    V8 emits these events even when CPU ticks collection is paused.
+//    The profiler uses the code events to maintain a function snapshot (list of
+//    code ranges assosiated with function name and source line info)
+//    (xdk-code-map.cc).
+//
+//    Start profiling
+//
+//      When the profiler receives a command to start profiling that it calls
+//      resumeSampling() (xdk/xdk-agent.cc) which
+//      1. Creates a new trace file to log the ticks and code events
+//      2. Puts the function snapshot into the trace file
+//      3. Resumes CPU ticks collection
+//
+//    Stop profiling
+//
+//      When the profiler receives a command to stop profiling that it calls
+//      pauseSampling() (xdk/xdk-agent.cc) which stops the CPU ticks collection.
+//      Note that the agent continues to consume the code events to maintain
+//      the function snapshot.
+//
+//      When collection is stopped that AppAnalyzer takes the trace file for
+//      processing.
+//
+// ----------------------------------------------------------------------------
+
+namespace xdk {
+
+// This function
+// - Overrides the V8 flags to specify a new logfile for writting profiling data
+//   (CPU ticks and Code* events).
+// - Registers callback to get line number info and code events from V8 built-in
+//   profiler. These data are needed to mantain the code map.
+// - Starts the XDK agent listener thread which is awaiting for start and stop
+//   profiling commands.
+void XDKInitializeForV8(v8::internal::Isolate* isolate);
+
+bool XDKIsAgentAlive();
+
+}  // namespace XDK
+
+#endif  // V8_XDK_H_
+
index 49912d1..429b8cb 100644 (file)
@@ -2622,7 +2622,7 @@ void Assembler::movups(const Operand& dst, XMMRegister src) {
 void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
   ASSERT(is_uint8(imm8));
   EnsureSpace ensure_space(this);
-  emit_optional_rex_32(src, dst);
+  emit_optional_rex_32(dst, src);
   emit(0x0F);
   emit(0xC6);
   emit_sse_operand(dst, src);
index d707dd2..0ca9fca 100644 (file)
@@ -2034,6 +2034,9 @@ void LCodeGen::DoBranch(LBranch* instr) {
     __ xorps(xmm_scratch, xmm_scratch);
     __ ucomisd(reg, xmm_scratch);
     EmitBranch(instr, not_equal);
+  } else if (r.IsSIMD128()) {
+    ASSERT(!info()->IsStub());
+    EmitBranch(instr, no_condition);
   } else {
     ASSERT(r.IsTagged());
     Register reg = ToRegister(instr->value());
@@ -2049,6 +2052,9 @@ void LCodeGen::DoBranch(LBranch* instr) {
     } else if (type.IsJSArray()) {
       ASSERT(!info()->IsStub());
       EmitBranch(instr, no_condition);
+    } else if (type.IsSIMD128()) {
+      ASSERT(!info()->IsStub());
+      EmitBranch(instr, no_condition);
     } else if (type.IsHeapNumber()) {
       ASSERT(!info()->IsStub());
       XMMRegister xmm_scratch = double_scratch0();
@@ -2129,6 +2135,18 @@ void LCodeGen::DoBranch(LBranch* instr) {
         __ j(equal, instr->TrueLabel(chunk_));
       }
 
+      if (expected.Contains(ToBooleanStub::FLOAT32x4)) {
+        // Float32x4 value -> true.
+        __ CmpInstanceType(map, FLOAT32x4_TYPE);
+        __ j(equal, instr->TrueLabel(chunk_));
+      }
+
+      if (expected.Contains(ToBooleanStub::INT32x4)) {
+        // Int32x4 value -> true.
+        __ CmpInstanceType(map, INT32x4_TYPE);
+        __ j(equal, instr->TrueLabel(chunk_));
+      }
+
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
         // heap number -> false iff +0, -0, or NaN.
         Label not_heap_number;
index 3832897..455c0ac 100644 (file)
@@ -982,7 +982,8 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
   if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
 
   bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
-      type.IsJSArray() || type.IsHeapNumber() || type.IsString();
+      type.IsJSArray() || type.IsHeapNumber() || type.IsSIMD128() ||
+      type.IsString();
   LInstruction* branch = new(zone()) LBranch(UseRegister(value));
   if (!easy_case &&
       ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) ||
diff --git a/src/v8/test/mjsunit/simd/builtin_operator.js b/src/v8/test/mjsunit/simd/builtin_operator.js
new file mode 100644 (file)
index 0000000..3336f74
--- /dev/null
@@ -0,0 +1,182 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --simd_object --allow-natives-syntax
+
+function testArithmeticOperators() {
+  var a = SIMD.float32x4.zero();
+  var b = SIMD.float32x4.zero();
+  var c;
+
+  c = a + b;
+  assertEquals(NaN, c);
+  c = a++;
+  assertEquals(NaN, c);
+  c = a - b;
+  assertEquals(NaN, c);
+  c = a--;
+  assertEquals(NaN, c);
+  c = a * b;
+  assertEquals(NaN, c);
+  c = a / b;
+  assertEquals(NaN, c);
+  c = a % b;
+  assertEquals(NaN, c);
+}
+
+testArithmeticOperators();
+testArithmeticOperators();
+%OptimizeFunctionOnNextCall(testArithmeticOperators);
+testArithmeticOperators();
+
+
+function testBitwiseOperators() {
+  var a = SIMD.float32x4.zero();
+  var b = SIMD.float32x4.zero();
+  var c;
+  c = a | b;
+  assertEquals(0, c);
+  c = a & b;
+  assertEquals(0, c);
+  c = a ^ b;
+  assertEquals(0, c);
+  c = ~a;
+  assertEquals(-1, c);
+  c = a << 0;
+  assertEquals(0, c);
+  c = a >> 0;
+  assertEquals(0, c);
+  c = a >>> 0;
+  assertEquals(0, c);
+}
+
+testBitwiseOperators();
+testBitwiseOperators();
+%OptimizeFunctionOnNextCall(testBitwiseOperators);
+testBitwiseOperators();
+
+
+function testAssignmentOperators() {
+  var a = SIMD.float32x4.zero();
+  var b = SIMD.float32x4.zero();
+  var c = a;
+  c += b;
+  assertEquals(NaN, c);
+  c -= b;
+  assertEquals(NaN, c);
+  c *= b;
+  assertEquals(NaN, c);
+  c /= b;
+  assertEquals(NaN, c);
+  c %= b;
+  assertEquals(NaN, c);
+
+  c &= b;
+  assertEquals(0, c);
+  c |= b;
+  assertEquals(0, c);
+  c ^= b;
+  assertEquals(0, c);
+  c <<= b;
+  assertEquals(0, c);
+  c >>= b;
+  assertEquals(0, c);
+  c >>>= b;
+  assertEquals(0, c);
+}
+
+testAssignmentOperators();
+testAssignmentOperators();
+%OptimizeFunctionOnNextCall(testAssignmentOperators);
+testAssignmentOperators();
+
+
+function testStringOperators() {
+  var a = SIMD.float32x4.zero();
+  var b = "0";
+  var c = a;
+  c += b;
+  assertEquals("float32x4(0,0,0,0)0", c);
+  c = b + a;
+  assertEquals("0float32x4(0,0,0,0)", c);
+}
+
+testStringOperators();
+testStringOperators();
+%OptimizeFunctionOnNextCall(testStringOperators);
+testStringOperators();
+
+
+function testComparisionOperators() {
+  var a = SIMD.float32x4.zero();
+  var b = SIMD.float32x4.zero();
+  assertEquals(true, a == b);
+  assertEquals(false, a != b);
+  assertEquals(true, a === b);
+  assertEquals(false, a !== b);
+  assertEquals(false, a > b);
+  assertEquals(true, a >= b);
+  assertEquals(false, a < b);
+  assertEquals(true, a <= b);
+}
+
+testComparisionOperators();
+testComparisionOperators();
+%OptimizeFunctionOnNextCall(testComparisionOperators);
+testComparisionOperators();
+
+
+function testLogicalOperators() {
+  var a = SIMD.float32x4.zero();
+  var b = SIMD.float32x4.splat(1);
+  assertEquals(1, (a && b).x);
+  assertEquals(1, (a && b).y);
+  assertEquals(1, (a && b).z);
+  assertEquals(1, (a && b).w);
+  assertEquals(0, (a || b).x);
+  assertEquals(0, (a || b).y);
+  assertEquals(0, (a || b).z);
+  assertEquals(0, (a || b).w);
+  assertEquals(false, !a);
+}
+
+testLogicalOperators();
+testLogicalOperators();
+%OptimizeFunctionOnNextCall(testLogicalOperators);
+testLogicalOperators();
+
+
+function testConditionalOperators() {
+  var a = SIMD.int32x4.zero();
+  var c = a ? 1 : 0;
+  assertEquals(1, c);
+}
+
+testConditionalOperators();
+testConditionalOperators();
+%OptimizeFunctionOnNextCall(testConditionalOperators);
+testConditionalOperators();
diff --git a/src/v8/test/mjsunit/simd/conversions.js b/src/v8/test/mjsunit/simd/conversions.js
new file mode 100644 (file)
index 0000000..d7002e5
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --simd_object --allow-natives-syntax
+
+function testObject() {
+  var a = SIMD.float32x4.zero();
+  var b = Object(a);
+  assertEquals(0, b.x);
+  assertEquals(0, b.y);
+  assertEquals(0, b.z);
+  assertEquals(0, b.w);
+  assertEquals(typeof(b), "object");
+  assertEquals(typeof(b.valueOf()), "float32x4");
+  assertEquals(Object.prototype.toString.call(b), "[object float32x4]");
+}
+
+testObject();
+testObject();
+%OptimizeFunctionOnNextCall(testObject);
+testObject();
+
+
+function testNumber() {
+  var a = SIMD.float32x4.zero();
+  var b = Number(a);
+  assertEquals(NaN, b);
+}
+
+testNumber();
+testNumber();
+%OptimizeFunctionOnNextCall(testNumber);
+testNumber();
+
+
+function testString() {
+  var a = SIMD.float32x4.zero();
+  var b = String(a);
+  assertEquals("float32x4(0,0,0,0)", b);
+}
+
+testString();
+testString();
+%OptimizeFunctionOnNextCall(testString);
+testString();
+
+
+function testBoolean() {
+  var a = SIMD.float32x4.zero();
+  var b = Boolean(a);
+  assertEquals(true, b);
+}
+
+testBoolean();
+testBoolean();
+%OptimizeFunctionOnNextCall(testBoolean);
+testBoolean();
index 11ba080..ccebcec 100755 (executable)
 #  - _GLOBAL__I__ZN2v810LineEditor6first_E
 #  - _GLOBAL__I__ZN2v88internal32AtomicOps_Internalx86CPUFeaturesE
 #  - _GLOBAL__I__ZN2v88internal8ThreadId18highest_thread_id_E
-expected_static_init_count=3
+
+# The XDK CPU profiler patch adds one more static initializer.
+# - _GLOBAL__sub_I__ZN3xdk8internal8XDKAgent9instance_E
+expected_static_init_count=4
 
 v8_root=$(readlink -f $(dirname $BASH_SOURCE)/../)
 
index 5dcd428..0898321 100644 (file)
         }, {
           'toolsets': ['target'],
         }],
+       ['v8_enable_xdkprof==1', {
+          'dependencies': ['../../src/third_party/xdk/xdk-v8.gyp:v8_xdk',],
+        }],
         ['v8_target_arch=="arm"', {
           'sources': [  ### gcmole(arch:arm) ###
             '../../src/arm/assembler-arm-inl.h',
index 272b398..877a87b 100644 (file)
@@ -7,9 +7,9 @@
 # Use 'Trunk' for trunk.
 # If using trunk, will use '.DEPS.git' for gclient.
 chromium_version = '35.0.1916.17'
-chromium_crosswalk_point = '634d34e4cf82b4f7400357c53ec12efaffe94add'
+chromium_crosswalk_point = 'e62582858402995e841741a28af1c418d815897f'
 blink_crosswalk_point = '2c4e1889f37db55c77215de4f113748f071cb7aa'
-v8_crosswalk_point = 'da94d1be519a0dc5ebc3d7bad06a973be91683c9'
+v8_crosswalk_point = 'd27abf42d305c5ee30cabed4926783bb105953c0'
 ozone_wayland_point = 'f4faec532d7d2f482b3ffe1e52be6fa3e6fc8629'
 
 deps_xwalk = {
index 0bd6ae0..7ac2bcc 100644 (file)
@@ -1,4 +1,4 @@
 MAJOR=6
 MINOR=35
-BUILD=121
+BUILD=131
 PATCH=0
index 7c39dde..ef07c24 100644 (file)
@@ -25,6 +25,7 @@
 
   <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
index 2bce33c..c4359d1 100644 (file)
@@ -15,7 +15,4 @@ found in the LICENSE file.
     <string name="dialog_message_update_runtime_lib_warning">An update is recommended for &quot;Crosswalk Runtime Library&quot;.</string>
     <string name="dialog_title_install_runtime_lib">Crosswalk Runtime Library not found</string>
     <string name="dialog_message_install_runtime_lib">Please install &quot;Crosswalk Runtime Library&quot; first.</string>
-    <string name="dialog_title_install_right_abi">Mismatch on process architecture between Crosswalk and your device</string>
-    <string name="dialog_message_install_right_abi_embedded">Please install %1$s packaged with Crosswalk for %2$s.</string>
-    <string name="dialog_message_install_right_abi_shared">Please install &quot;Crosswalk Runtime Library&quot; for %1$s.</string>
 </resources>
index a573d8a..f07ac77 100644 (file)
@@ -26,6 +26,7 @@
 
   <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
diff --git a/src/xwalk/app/android/app_template/res/drawable/launchscreen_bg.xml b/src/xwalk/app/android/app_template/res/drawable/launchscreen_bg.xml
new file mode 100644 (file)
index 0000000..1593500
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <!-- Background Color -->
+    <item>
+        <shape android:shape="rectangle" >
+            <solid android:color="#000000" />
+        </shape>
+    </item>
+    <!-- Background Image -->
+
+</layer-list>
index 2bce33c..c4359d1 100644 (file)
@@ -15,7 +15,4 @@ found in the LICENSE file.
     <string name="dialog_message_update_runtime_lib_warning">An update is recommended for &quot;Crosswalk Runtime Library&quot;.</string>
     <string name="dialog_title_install_runtime_lib">Crosswalk Runtime Library not found</string>
     <string name="dialog_message_install_runtime_lib">Please install &quot;Crosswalk Runtime Library&quot; first.</string>
-    <string name="dialog_title_install_right_abi">Mismatch on process architecture between Crosswalk and your device</string>
-    <string name="dialog_message_install_right_abi_embedded">Please install %1$s packaged with Crosswalk for %2$s.</string>
-    <string name="dialog_message_install_right_abi_shared">Please install &quot;Crosswalk Runtime Library&quot; for %1$s.</string>
 </resources>
index 5ad954c..18ca87a 100644 (file)
@@ -164,19 +164,6 @@ public abstract class XWalkRuntimeActivityBase extends Activity implements Cross
                 title = getString("dialog_title_install_runtime_lib");
                 message = getString("dialog_message_install_runtime_lib");
                 break;
-            case XWalkRuntimeLibraryException.XWALK_CORE_LIBRARY_SO_NOT_EXIST:
-                title = getString("dialog_title_install_right_abi");
-                if (XWalkRuntimeClient.libraryIsEmbedded()) {
-                    String appName = getPackageManager().getApplicationLabel(
-                            getApplicationContext().getApplicationInfo()).toString();
-                    if (appName == null) appName = getApplicationContext().getPackageName();
-                    message = String.format(getString("dialog_message_install_right_abi_embedded"),
-                            appName, System.getProperty("os.arch"));
-                } else {
-                    message = String.format(getString("dialog_message_install_right_abi_shared"),
-                            System.getProperty("os.arch"));
-                }
-                break;
             case XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_INVOKE_FAILED:
             default:
                 Exception originException = runtimeException.getOriginException();
index c3d4d05..f5d6861 100644 (file)
@@ -112,36 +112,23 @@ public class XWalkRuntimeClient extends CrossPackageWrapper {
 
     @Override
     public void handleException(Exception e) {
+        // Here is for handling runtime library not found,
+        // Should never happen if runtime is embedded.
+        if (libraryIsEmbedded()) throw new RuntimeException(e);
+
+        // XWalkView will handle UnsatisfiedLinkError which indicates mismatch of CPU architecture.
+        // So exception here should be either library not installed for shared mode or invoke error.
         Exception toHandle = e;
-        boolean wrongNativeLibraryAbi = false;
         if (mRuntimeLoaded) {
             toHandle = new XWalkRuntimeLibraryException(
                     XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_INVOKE_FAILED, e);
         } else {
             if (!(e instanceof XWalkRuntimeLibraryException)) {
-                Throwable rootCause = e;
-                while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
-                    rootCause = rootCause.getCause();
-                }
-                // UnsatisfiedLinkError happens when the libxwalkcore.so is not found.
-                // If the runtime library package exist, but the native library not, it can
-                // be considered that the installed runtime lib apk is for another cpu
-                // architecture.
-                if (rootCause instanceof UnsatisfiedLinkError) {
-                    wrongNativeLibraryAbi = true;
-                    toHandle = new XWalkRuntimeLibraryException(
-                            XWalkRuntimeLibraryException.XWALK_CORE_LIBRARY_SO_NOT_EXIST, e);
-                } else {
-                    toHandle = new XWalkRuntimeLibraryException(
-                            XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_NOT_INSTALLED, e);
-                }
+                toHandle = new XWalkRuntimeLibraryException(
+                        XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_NOT_INSTALLED, e);
             }
         }
-        // Here is for handling runtime library not found or not match,
-        // if library is embedded, should not invoke it.
-        // Except the error is for incorrect abi, which could also happen for
-        // embedded mode.
-        if (!libraryIsEmbedded() || wrongNativeLibraryAbi) super.handleException(toHandle);
+        super.handleException(toHandle);
     }
 
     public FrameLayout get() {
index 41ec4ad..8fc5d63 100644 (file)
@@ -19,8 +19,7 @@ public class XWalkRuntimeLibraryException extends Exception {
     public final static int XWALK_RUNTIME_LIBRARY_NOT_INSTALLED = 1;
     public final static int XWALK_RUNTIME_LIBRARY_NOT_UP_TO_DATE_CRITICAL = 2;
     public final static int XWALK_RUNTIME_LIBRARY_NOT_UP_TO_DATE_WARNING = 3;
-    public final static int XWALK_CORE_LIBRARY_SO_NOT_EXIST = 4;
-    public final static int XWALK_RUNTIME_LIBRARY_INVOKE_FAILED = 5;
+    public final static int XWALK_RUNTIME_LIBRARY_INVOKE_FAILED = 4;
     
     private int mType;
     private Exception mOriginException;
index 95de602..febc0f3 100644 (file)
@@ -29,6 +29,7 @@
   <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
index 1578ed6..dd98c68 100644 (file)
@@ -29,6 +29,7 @@
   <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
index 1280cf4..27123df 100755 (executable)
@@ -11,6 +11,7 @@ import re
 import shutil
 import sys
 
+from customize_launch_screen import CustomizeLaunchScreen
 from handle_xml import AddElementAttribute
 from handle_xml import AddElementAttributeAndText
 from handle_xml import EditElementAttribute
@@ -27,7 +28,7 @@ def ReplaceInvalidChars(value, mode='default'):
   if mode == 'default':
     invalid_chars = '\/:*?"<>|- '
   elif mode == 'apkname':
-    invalid_chars = '\/:.*?"<>|-'
+    invalid_chars = '\/:.*?"<>|- '
   for c in invalid_chars:
     if mode == 'apkname' and c in value:
       print("Illegal character: '%s' is replaced with '_'" % c)
@@ -76,46 +77,29 @@ def CustomizeStringXML(sanitized_name, description):
     strings_file.close()
 
 
-def CustomizeThemeXML(sanitized_name, fullscreen, launch_screen_img):
+def CustomizeThemeXML(sanitized_name, fullscreen, app_manifest):
   theme_path = os.path.join(sanitized_name, 'res', 'values', 'theme.xml')
   if not os.path.isfile(theme_path):
     print('Error: theme.xml is missing in the build tool.')
     sys.exit(6)
 
-  xmldoc = minidom.parse(theme_path)
+  theme_xmldoc = minidom.parse(theme_path)
   if fullscreen:
-    EditElementValueByNodeName(xmldoc, 'item',
+    EditElementValueByNodeName(theme_xmldoc, 'item',
                                'android:windowFullscreen', 'true')
-  if launch_screen_img:
-    EditElementValueByNodeName(xmldoc, 'item',
+  has_background = CustomizeLaunchScreen(app_manifest, sanitized_name)
+  if has_background:
+    EditElementValueByNodeName(theme_xmldoc, 'item',
                                'android:windowBackground',
-                               '@drawable/launchscreen')
-    default_image = launch_screen_img
-    if os.path.isfile(default_image):
-      drawable_path = os.path.join(sanitized_name, 'res', 'drawable')
-      if not os.path.exists(drawable_path):
-        os.makedirs(drawable_path)
-      # Get the extension of default_image.
-      # Need to take care of special case, such as 'img.9.png'
-      name = os.path.basename(default_image)
-      extlist = name.split('.')
-      # Remove the file name from the list.
-      extlist.pop(0)
-      ext = '.' + '.'.join(extlist)
-      final_launch_screen_path = os.path.join(drawable_path,
-                                              'launchscreen' + ext)
-      shutil.copyfile(default_image, final_launch_screen_path)
-    else:
-      print('Error: Please make sure \"' + default_image + '\" exists!')
-      sys.exit(6)
-  theme_file = open(theme_path, 'w')
-  xmldoc.writexml(theme_file, encoding='utf-8')
+                               '@drawable/launchscreen_bg')
+  theme_file = open(theme_path, 'wb')
+  theme_xmldoc.writexml(theme_file, encoding='utf-8')
   theme_file.close()
 
 
 def CustomizeXML(sanitized_name, package, app_versionCode, app_version,
                  description, name, orientation, icon_dict, fullscreen,
-                 icon, launch_screen_img, permissions, app_root):
+                 icon, app_manifest, permissions, app_root):
   manifest_path = os.path.join(sanitized_name, 'AndroidManifest.xml')
   if not os.path.isfile(manifest_path):
     print ('Please make sure AndroidManifest.xml'
@@ -123,7 +107,7 @@ def CustomizeXML(sanitized_name, package, app_versionCode, app_version,
     sys.exit(6)
 
   CustomizeStringXML(sanitized_name, description)
-  CustomizeThemeXML(sanitized_name, fullscreen, launch_screen_img)
+  CustomizeThemeXML(sanitized_name, fullscreen, app_manifest)
   xmldoc = minidom.parse(manifest_path)
   EditElementAttribute(xmldoc, 'manifest', 'package', package)
   if app_versionCode:
@@ -177,7 +161,8 @@ def SetVariable(file_path, string_line, variable, value):
 
 
 def CustomizeJava(sanitized_name, package, app_url, app_local_path,
-                  enable_remote_debugging, display_as_fullscreen):
+                  enable_remote_debugging, display_as_fullscreen,
+                  keep_screen_on):
   root_path =  os.path.join(sanitized_name, 'src',
                             package.replace('.', os.path.sep))
   dest_activity = os.path.join(root_path, sanitized_name + 'Activity.java')
@@ -212,6 +197,12 @@ def CustomizeJava(sanitized_name, package, app_url, app_local_path,
     SetVariable(dest_activity,
                 'super.onCreate(savedInstanceState)',
                 'IsFullscreen', 'true')
+  if keep_screen_on:
+    ReplaceString(
+        dest_activity,
+        'super.onCreate(savedInstanceState);',
+        'super.onCreate(savedInstanceState);\n        '+
+        'getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);')
 
 
 def CopyExtensionFile(extension_name, suffix, src_path, dest_path):
@@ -323,7 +314,7 @@ def CustomizeExtensions(sanitized_name, name, extensions):
 
         # Write to the manifest file to save the update.
         file_handle = open(manifest_path, 'w')
-        xmldoc.writexml(file_handle)
+        xmldoc.writexml(file_handle, encoding='utf-8')
         file_handle.close()
 
   # Write configuration of extensions into the target extensions-config.json.
@@ -403,19 +394,20 @@ def CustomizeIcon(sanitized_name, app_root, icon, icon_dict):
 
 def CustomizeAll(app_versionCode, description, icon_dict, permissions, app_url,
                  app_root, app_local_path, enable_remote_debugging,
-                 display_as_fullscreen, extensions, launch_screen_img,
-                 icon, package='org.xwalk.app.template', name='AppTemplate',
-                 app_version='1.0.0', orientation='unspecified',
-                 xwalk_command_line=''):
+                 display_as_fullscreen, keep_screen_on, extensions,
+                 app_manifest, icon, package='org.xwalk.app.template',
+                 name='AppTemplate', app_version='1.0.0',
+                 orientation='unspecified', xwalk_command_line=''):
   sanitized_name = ReplaceInvalidChars(name, 'apkname')
   try:
     Prepare(sanitized_name, package, app_root)
     CustomizeXML(sanitized_name, package, app_versionCode, app_version,
                  description, name, orientation, icon_dict,
-                 display_as_fullscreen, icon, launch_screen_img, permissions,
+                 display_as_fullscreen, icon, app_manifest, permissions,
                  app_root)
     CustomizeJava(sanitized_name, package, app_url, app_local_path,
-                  enable_remote_debugging, display_as_fullscreen)
+                  enable_remote_debugging, display_as_fullscreen,
+                  keep_screen_on)
     CustomizeExtensions(sanitized_name, name, extensions)
     GenerateCommandLineFile(sanitized_name, xwalk_command_line)
   except SystemExit as ec:
@@ -459,6 +451,8 @@ def main():
   parser.add_option('-f', '--fullscreen', action='store_true',
                     dest='fullscreen', default=False,
                     help='Make application fullscreen.')
+  parser.add_option('--keep-screen-on', action='store_true', default=False,
+                    help='Support keeping screen on')
   info = ('The path list for external extensions separated by os separator.'
           'On Linux and Mac, the separator is ":". On Windows, it is ";".'
           'Such as: --extensions="/path/to/extension1:/path/to/extension2"')
@@ -469,13 +463,13 @@ def main():
           'http://developer.android.com/guide/topics/manifest/'
           'activity-element.html#screen')
   parser.add_option('--orientation', help=info)
-  parser.add_option('--launch-screen-img',
-                    help='The fallback image for launch_screen')
+  parser.add_option('--manifest', help='The manifest path')
   info = ('Use command lines.'
           'Crosswalk is powered by Chromium and supports Chromium command line.'
           'For example, '
           '--xwalk-command-line=\'--chromium-command-1 --xwalk-command-2\'')
   parser.add_option('--xwalk-command-line', default='', help=info)
+
   options, _ = parser.parse_args()
   try:
     icon_dict = {144: 'icons/icon_144.png',
@@ -496,10 +490,11 @@ def main():
     CustomizeAll(options.app_versionCode, options.description, icon_dict,
                  options.permissions, options.app_url, options.app_root,
                  options.app_local_path, options.enable_remote_debugging,
-                 options.fullscreen, options.extensions,
-                 options.launch_screen_img, icon, options.package, options.name,
+                 options.fullscreen, options.keep_screen_on, options.extensions,
+                 options.manifest, icon, options.package, options.name,
                  options.app_version, options.orientation,
                  options.xwalk_command_line)
+
   except SystemExit as ec:
     print('Exiting with error code: %d' % ec.code)
     return ec.code
diff --git a/src/xwalk/app/tools/android/customize_launch_screen.py b/src/xwalk/app/tools/android/customize_launch_screen.py
new file mode 100755 (executable)
index 0000000..f6f1bf8
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+
+# 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.
+
+import os
+import shutil
+import sys
+
+from manifest_json_parser import ManifestJsonParser
+
+def CopyToPathWithName(root, name, final_path, rename):
+  if name == '':
+    return False
+  origin_path = os.path.join(root, name)
+  if not os.path.exists(origin_path):
+    print ('Error: \'' + origin_path + '\' not found.' )
+    sys.exit(6)
+  if not os.path.exists(final_path):
+    os.makedirs(final_path)
+  # Get the extension.
+  # Need to take care of special case, such as 'img.9.png'
+  name_components = name.split('.')
+  name_components[0] = rename
+  new_name = '.'.join(name_components)
+  final_path_with_name = os.path.join(final_path, new_name)
+  shutil.copyfile(origin_path, final_path_with_name)
+  return True
+
+
+def CopyDrawables(image_dict, orientation, sanitized_name, name, app_root):
+  drawable = os.path.join(sanitized_name, 'res', 'drawable')
+  if orientation == 'landscape':
+    drawable = drawable + '-land'
+  elif orientation == 'portrait':
+    drawable = drawable + '-port'
+  drawable_ldpi = drawable + '-ldpi'
+  drawable_mdpi = drawable + '-mdpi'
+  drawable_hdpi = drawable + '-hdpi'
+  drawable_xhdpi = drawable + '-xhdpi'
+
+  image_075x = image_dict.get('0.75x', '')
+  image_1x = image_dict.get('1x', '')
+  image_15x = image_dict.get('1.5x', '')
+  image_2x = image_dict.get('2x', '')
+
+  # Copy all supported images: 0.75x, 1x, 1.5x, 2x.
+  has_image = False
+  if image_075x:
+    if CopyToPathWithName(app_root, image_075x, drawable_ldpi, name):
+      has_image = True
+  if image_1x:
+    if CopyToPathWithName(app_root, image_1x, drawable_mdpi, name):
+      has_image = True
+  if image_15x:
+    if CopyToPathWithName(app_root, image_15x, drawable_hdpi, name):
+      has_image = True
+  if image_2x:
+    if CopyToPathWithName(app_root, image_2x, drawable_xhdpi, name):
+      has_image = True
+
+  # If no supported images found, find the closest one as 1x.
+  if not has_image:
+    closest = ''
+    delta = sys.maxint
+    for (k , v) in  image_dict.items():
+      items = k.split('x')
+      if len(items) == 2:
+        float_value = sys.maxint
+        try:
+          float_value = float(items[0])
+        except ValueError:
+          continue
+        if abs(float_value - 1) < delta:
+          closest = v
+          if CopyToPathWithName(app_root, closest, drawable_mdpi, name):
+            delta = float_value
+
+
+def CustomizeDrawable(image, orientation, sanitized_name, app_root, name):
+  # Parse the image.
+  # The format of image: 'image-1x.png [1x], image-75x.png 0.75x,
+  #                       image-15x.png 1.5x, image-2x.png 2x'
+  image_list = image.split(',')
+
+  # The first image: 'image-1x.png', the density is not provided.
+  image_pair_1 = image_list[0].strip()
+  items = image_pair_1.split(' ')
+  image_1x = ''
+  if len(items) == 1:
+    image_1x = items[0]
+    image_list.pop(0)
+  # The dictionary which contains the image pair.
+  image_dict = {'1x': image_1x}
+
+  for image_pair in image_list:
+    items = image_pair.strip().split(' ')
+    if len(items) >= 2:
+      x = items[len(items)-1]
+      image_item = items[0]
+      image_dict[x] = image_item
+
+  CopyDrawables(image_dict, orientation, sanitized_name, name, app_root)
+
+
+def CustomizeForeground(image, orientation, sanitized_name, app_root):
+  CustomizeDrawable(image, orientation, sanitized_name,
+                    app_root, "launchscreen_img")
+
+
+def CustomizeBackground(background_color,
+                        background_image,
+                        orientation,
+                        sanitized_name,
+                        app_root):
+  background_path = os.path.join(sanitized_name, 'res',
+                                 'drawable', 'launchscreen_bg.xml')
+  if not os.path.isfile(background_path):
+    print('Error: launchscreen_bg.xml is missing in the build tool.')
+    sys.exit(6)
+
+  has_background = False
+  background_file = open(background_path, 'r')
+  content = background_file.read()
+  background_file.close()
+  # Fill the background_color.
+  if background_color:
+    content = content.replace('#000000', background_color, 1)
+    has_background = True
+  # Fill the background_image.
+  if background_image:
+    CustomizeDrawable(background_image, orientation, sanitized_name,
+                      app_root, "launchscreen_bg_img")
+    # Only set Background Image once for each orientation.
+    tmp = '<item>\n' \
+          '  <bitmap\n' \
+          '    android:src=\"@drawable/launchscreen_bg_img\"\n' \
+          '    android:tileMode=\"repeat\" />\n' \
+          '</item>\n'
+    content = content.replace('<!-- Background Image -->', tmp, 1)
+    has_background = True
+  if has_background:
+    background_file = file(background_path,'w')
+    background_file.write(content)
+    background_file.close()
+  return has_background
+
+
+def CustomizeByOrientation(parser, orientation, sanitized_name, app_root):
+  background_color = parser.GetLaunchScreenBackgroundColor(orientation)
+  background_image = parser.GetLaunchScreenBackgroundImage(orientation)
+  image = parser.GetLaunchScreenImage(orientation)
+  # Customize background: background_color, background_image.
+  has_background = CustomizeBackground(background_color, background_image,
+                                       orientation, sanitized_name, app_root)
+  # Customize foreground: image.
+  CustomizeForeground(image, orientation, sanitized_name, app_root)
+  return has_background
+
+
+def CustomizeLaunchScreen(app_manifest, sanitized_name):
+  if not app_manifest:
+    return False
+  parser = ManifestJsonParser(os.path.expanduser(app_manifest))
+  app_root = os.path.dirname(app_manifest)
+  default = CustomizeByOrientation(parser, 'default',
+                                   sanitized_name, app_root)
+  portrait = CustomizeByOrientation(parser, 'portrait',
+                                    sanitized_name, app_root)
+  landscape = CustomizeByOrientation(parser, 'landscape',
+                                     sanitized_name, app_root)
+  return default or portrait or landscape
index fc54b3f..563681e 100755 (executable)
@@ -116,9 +116,6 @@ def ParseManifest(options):
     options.fullscreen = True
   elif parser.GetFullScreenFlag().lower() == 'false':
     options.fullscreen = False
-  if parser.GetLaunchScreenImg():
-    options.launch_screen_img  = os.path.join(options.app_root,
-                                              parser.GetLaunchScreenImg())
 
 
 def ParseXPK(options, out_dir):
@@ -209,8 +206,8 @@ def Customize(options):
   CustomizeAll(app_versionCode, options.description, options.icon_dict,
                options.permissions, options.app_url, app_root,
                options.app_local_path, remote_debugging,
-               fullscreen_flag, options.extensions,
-               options.launch_screen_img, icon, package, name, app_version,
+               fullscreen_flag, options.keep_screen_on, options.extensions,
+               options.manifest, icon, package, name, app_version,
                orientation, options.xwalk_command_line)
 
 
@@ -524,14 +521,24 @@ def MakeApk(options, sanitized_name):
       valid_archs = ['x86', 'armeabi-v7a']
       packaged_archs = []
       for arch in valid_archs:
-        if os.path.isfile(os.path.join('native_libs', arch, 'libs',
-                                       arch, 'libxwalkcore.so')):
+        lib_path = os.path.join('native_libs', arch, 'libs',
+                                arch, 'libxwalkcore.so')
+        if os.path.isfile(lib_path):
           if arch.find('x86') != -1:
             options.arch = 'x86'
           elif arch.find('arm') != -1:
             options.arch = 'arm'
           Execution(options, sanitized_name)
           packaged_archs.append(options.arch)
+        else:
+          print('Warning: failed to create package for arch "%s" '
+                'due to missing library %s' %
+                (arch, lib_path))
+
+      if len(packaged_archs) == 0:
+        print('No packages created, aborting')
+        sys.exit(13)
+
       multi_arch = False
       if len(packaged_archs) >=2:
         multi_arch = True
@@ -639,6 +646,8 @@ def main(argv):
   group.add_option('-f', '--fullscreen', action='store_true',
                    dest='fullscreen', default=False,
                    help='Make application fullscreen.')
+  group.add_option('--keep-screen-on', action='store_true', default=False,
+                   help='Support keeping screen on')
   info = ('The path of application icon. '
           'Such as: --icon=/path/to/your/customized/icon')
   group.add_option('--icon', help=info)
@@ -676,10 +685,6 @@ def main(argv):
     parser.print_help()
     return 0
 
-  # This option will not export to users.
-  # Initialize here and will be read from manifest.json.
-  options.launch_screen_img = ''
-
   if options.version:
     if os.path.isfile('VERSION'):
       print(GetVersion('VERSION'))
@@ -703,6 +708,10 @@ def main(argv):
     if not options.package:
       parser.error('The package name is required! '
                    'Please use "--package" option.')
+    elif len(options.package) >= 128 :
+      parser.error('To be safe, the length of package name '
+                   'should be less than 128.')
+
     if not options.name:
       parser.error('The APK name is required! Please use "--name" option.')
     if not ((options.app_url and not options.app_root
index 6efbf21..6560542 100755 (executable)
@@ -155,14 +155,14 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--app-version=1.0.0',
            '--package=org.xwalk.example', self._mode]
     out = RunCommand(cmd)
-    self.assertTrue(out.find('The APK name is required!') != -1)
     Clean('Example', '1.0.0')
+    self.assertTrue(out.find('The APK name is required!') != -1)
     cmd = ['python', 'make_apk.py', '--name="Test Example"',
            '--app-version=1.0.0',
            '--package=org.xwalk.example', self._mode]
     out = RunCommand(cmd)
-    self.assertTrue(out.find('The APK name is required!') == -1)
     Clean('Test Example', '1.0.0')
+    self.assertTrue(out.find('The APK name is required!') == -1)
     # The following invalid chars verification is too heavy for embedded mode,
     # and the result of verification should be the same between shared mode
     # and embedded mode. So only do the verification in the shared mode.
@@ -174,8 +174,8 @@ class TestMakeApk(unittest.TestCase):
                '--app-version=1.0.0', '--package=org.xwalk.example',
                '--app-url=http://www.intel.com', self._mode]
         out = RunCommand(cmd)
-        self.assertTrue(out.find('Illegal character') != -1)
         Clean('Example_', '1.0.0')
+        self.assertTrue(out.find('Illegal character') != -1)
 
   def testToolVersion(self):
     cmd = ['python', 'make_apk.py', '--version']
@@ -188,6 +188,7 @@ class TestMakeApk(unittest.TestCase):
            '--description=a sample application',
            '--app-url=http://www.intel.com', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
@@ -195,7 +196,6 @@ class TestMakeApk(unittest.TestCase):
     self.assertTrue(content.find('description') != -1)
     self.assertTrue(content.find('versionName') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testAppVersionCode(self):
     cmd = ['python', 'make_apk.py', '--name=Example',
@@ -204,13 +204,13 @@ class TestMakeApk(unittest.TestCase):
            '--app-versionCode=3',
            '--app-url=http://www.intel.com', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
     self.assertTrue(os.path.exists(manifest))
     self.assertTrue(content.find('versionCode="3"') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testAppVersionCodeBase(self):
     # Arch option only works for embedded mode,
@@ -230,13 +230,13 @@ class TestMakeApk(unittest.TestCase):
            arch,
            '--app-url=http://www.intel.com', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
     self.assertTrue(os.path.exists(manifest))
     self.assertTrue(content.find(versionCode) != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testAppBigVersionCodeBase(self):
     # Arch option only works for embedded mode,
@@ -254,22 +254,22 @@ class TestMakeApk(unittest.TestCase):
            arch,
            '--app-url=http://www.intel.com', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     self.assertFalse(os.path.exists(manifest))
-    Clean('Example', '1.0.0')
 
   def testPermissions(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', '--permissions=geolocation',
            '--app-url=http://www.intel.com', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
     self.assertTrue(os.path.exists(manifest))
     self.assertTrue(content.find('ACCESS_FINE_LOCATION') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testPermissionsWithError(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
@@ -288,19 +288,20 @@ class TestMakeApk(unittest.TestCase):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            self._mode]
     out = RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(out.find('The package name is required!') != -1)
     Clean('Example', '1.0.0')
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', self._mode]
     out = RunCommand(cmd)
     self.assertTrue(out.find('The package name is required!') == -1)
-    Clean('Example', '1.0.0')
 
   def testEntry(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            self._mode]
     out = RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(out.find('The entry is required.') == -1)
     self.checkApks('Example', '1.0.0')
     Clean('Example', '1.0.0')
@@ -312,12 +313,12 @@ class TestMakeApk(unittest.TestCase):
     out = RunCommand(cmd)
     self.assertTrue(out.find('The entry is required.') == -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testEntryWithErrors(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', self._mode]
     out = RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(out.find('The entry is required.') != -1)
     self.assertFalse(os.path.exists('Example.apk'))
     Clean('Example', '1.0.0')
@@ -351,7 +352,6 @@ class TestMakeApk(unittest.TestCase):
     out = RunCommand(cmd)
     self.assertTrue(out.find('Please make sure that the local path file') != -1)
     self.assertFalse(os.path.exists('Example.apk'))
-    Clean('Example', '1.0.0')
 
   def testIconByOption(self):
     icon = os.path.join('test_data', 'manifest', 'icons', 'icon_96.png')
@@ -359,12 +359,12 @@ class TestMakeApk(unittest.TestCase):
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '--icon=%s' % icon, self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
     self.assertTrue(content.find('drawable/icon_96') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testIconByManifest(self):
     manifest_path = os.path.join('test_data', 'manifest', 'manifest_icon.json')
@@ -372,18 +372,19 @@ class TestMakeApk(unittest.TestCase):
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '--manifest=%s' % manifest_path, self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
     self.assertTrue(content.find('drawable/icon') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testFullscreen(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '-f', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     theme = 'Example/res/values/theme.xml'
     with open(theme, 'r') as content_file:
       content = content_file.read()
@@ -392,13 +393,13 @@ class TestMakeApk(unittest.TestCase):
         content.find(
             '<item name="android:windowFullscreen">true</item>') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testEnableRemoteDebugging(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '--enable-remote-debugging', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     activity = 'Example/src/org/xwalk/example/ExampleActivity.java'
     with open(activity, 'r') as content_file:
       content = content_file.read()
@@ -416,7 +417,6 @@ class TestMakeApk(unittest.TestCase):
     self.assertTrue(os.path.exists(activity))
     self.assertTrue(content.find('setRemoteDebugging') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testKeystore(self):
     keystore_path = os.path.join('test_data', 'keystore', 'xwalk-test.keystore')
@@ -425,6 +425,7 @@ class TestMakeApk(unittest.TestCase):
            '--keystore-path=%s' % keystore_path, '--keystore-alias=xwalk-test',
            '--keystore-passcode=xwalk-test', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(os.path.exists('Example'))
     apk_list = ['Example.apk', 'Example_x86.apk', 'Example_arm.apk']
     for apk in apk_list:
@@ -434,12 +435,12 @@ class TestMakeApk(unittest.TestCase):
         out = RunCommand(cmd)
         self.assertTrue(out.find('smk') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testManifest(self):
     manifest_path = os.path.join('test_data', 'manifest', 'manifest.json')
     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path, self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
@@ -461,16 +462,15 @@ class TestMakeApk(unittest.TestCase):
             '<item name="android:windowFullscreen">true</item>') != -1)
     self.assertTrue(os.path.exists('Example'))
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testManifestWithSpecificValue(self):
     manifest_path = os.path.join('test_data', 'manifest',
                                  'manifest_app_launch_local_path.json')
     cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path, self._mode]
     out = RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(out.find('no app launch path') == -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testManifestWithError(self):
     manifest_path = os.path.join('test_data', 'manifest',
@@ -518,6 +518,7 @@ class TestMakeApk(unittest.TestCase):
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '--extensions=%s' % extension_path, self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(os.path.exists('Example'))
     extensions_config_json = 'Example/assets/extensions-config.json'
     self.assertTrue(os.path.exists(extensions_config_json))
@@ -530,7 +531,6 @@ class TestMakeApk(unittest.TestCase):
     extension_jar = 'Example/xwalk-extensions/myextension/myextension.jar'
     self.assertTrue(os.path.exists(extension_jar))
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testExtensionsWithNonExtension(self):
     # Test with a non-existed extension.
@@ -552,6 +552,7 @@ class TestMakeApk(unittest.TestCase):
            '--app-local-path=contactextension.html',
            '--extensions=%s' % extension_path, self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(os.path.exists('Example'))
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
@@ -560,15 +561,14 @@ class TestMakeApk(unittest.TestCase):
     self.assertTrue(content.find('android.permission.WRITE_CONTACTS') != -1)
     self.assertTrue(content.find('android.permission.READ_CONTACTS') != -1)
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testXPK(self):
     xpk_file = os.path.join('test_data', 'xpk', 'example.xpk')
     cmd = ['python', 'make_apk.py', '--xpk=%s' % xpk_file, self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(os.path.exists('Example'))
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testXPKWithError(self):
     xpk_file = os.path.join('test_data', 'xpk', 'error.xpk')
@@ -583,6 +583,7 @@ class TestMakeApk(unittest.TestCase):
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '--orientation=landscape', self._mode]
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
@@ -590,7 +591,6 @@ class TestMakeApk(unittest.TestCase):
     self.assertTrue(content.find('landscape') != -1)
     self.assertTrue(os.path.exists('Example'))
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def testArch(self):
     # Arch option only works for embedded mode,
@@ -600,6 +600,7 @@ class TestMakeApk(unittest.TestCase):
              '--package=org.xwalk.example', '--app-url=http://www.intel.com',
              '--arch=x86', self._mode]
       RunCommand(cmd)
+      self.addCleanup(Clean, 'Example', '1.0.0')
       if 'x86' in self.archs():
         self.assertTrue(os.path.isfile('Example_1.0.0_x86.apk'))
         self.checkApk('Example_1.0.0_x86.apk', 'x86')
@@ -617,19 +618,18 @@ class TestMakeApk(unittest.TestCase):
       else:
         self.assertFalse(os.path.isfile('Example_1.0.0._arm.apk'))
       self.assertFalse(os.path.isfile('Example_1.0.0_x86.apk'))
-      Clean('Example', '1.0.0')
 
   def testVerbose(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
            '--verbose', self._mode]
     result = RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     self.assertTrue(result.find('aapt') != -1)
     self.assertTrue(result.find('crunch') != -1)
     self.assertTrue(result.find('apkbuilder') != -1)
     self.assertTrue(os.path.exists('Example'))
     self.checkApks('Example', '1.0.0')
-    Clean('Example', '1.0.0')
 
   def executeCommandAndVerifyResult(self, exec_file):
     # Test all of supported options with empty 'mode' option.
@@ -648,18 +648,22 @@ class TestMakeApk(unittest.TestCase):
            '--enable-remote-debugging',
            '--extensions=%s' % extension_path,
            '--fullscreen',
+           '--keep-screen-on',
            '%s' % icon,
            '--name=Example',
            '--orientation=landscape',
            '--package=org.xwalk.example',
            '--permissions=geolocation']
     RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
     activity = 'Example/src/org/xwalk/example/ExampleActivity.java'
     with open(activity, 'r') as content_file:
       content = content_file.read()
     self.assertTrue(os.path.exists(activity))
     # Test remote debugging option.
     self.assertTrue(content.find('setRemoteDebugging') != -1)
+    # Test keep screen on option
+    self.assertTrue(content.find('FLAG_KEEP_SCREEN_ON') != -1)
 
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
@@ -693,14 +697,6 @@ class TestMakeApk(unittest.TestCase):
     self.assertTrue(os.path.exists(extension_js))
     extension_jar = 'Example/xwalk-extensions/myextension/myextension.jar'
     self.assertTrue(os.path.exists(extension_jar))
-    # Test arch option.
-    if 'x86' in self.archs():
-      self.assertTrue(os.path.isfile('Example_1.0.0_x86.apk'))
-      self.checkApk('Example_1.0.0_x86.apk', 'x86')
-    else:
-      self.assertFalse(os.path.isfile('Example_1.0.0_x86.apk'))
-    self.assertFalse(os.path.isfile('Example_1.0.0_arm.apk'))
-    Clean('Example', '1.0.0')
 
   def testEmptyMode(self):
     self.executeCommandAndVerifyResult('make_apk.py')
@@ -728,6 +724,7 @@ class TestMakeApk(unittest.TestCase):
              '--package=org.xwalk.example', '--app-url=http://www.intel.com',
              '--target-dir=%s' % option, self._mode]
       RunCommand(cmd)
+      self.addCleanup(Clean, os.path.expanduser('%sExample' % option), '1.0.0')
       if self._mode.find('shared') != -1:
         apk_path = os.path.expanduser('%sExample_1.0.0.apk' % option)
         self.assertTrue(os.path.exists(apk_path))
@@ -738,7 +735,6 @@ class TestMakeApk(unittest.TestCase):
                                         % (option, arch))
           self.assertTrue(os.path.exists(apk_path))
           self.checkApk(apk_path, arch)
-      Clean(os.path.expanduser('%sExample' % option), '1.0.0')
 
 
 def SuiteWithModeOption():
@@ -825,6 +821,7 @@ if __name__ == '__main__':
     options.mode = 'shared'
     print 'Run tests in shared mode.'
     test_result = TestSuiteRun(runner, mode_suite) and test_result
+    options.mode = ''
     print 'Run test without \'--mode\' option.'
     test_result = TestSuiteRun(runner, empty_mode_suite) and test_result
   if not test_result:
index 9f61231..f3ac84c 100755 (executable)
@@ -138,18 +138,28 @@ class ManifestJsonParser(object):
       ret_dict['fullscreen'] = 'true'
     else:
       ret_dict['fullscreen'] = ''
-    ret_dict['launch_screen_img'] = ''
     if 'launch_screen' in self.data_src:
-      if 'default' not in self.data_src['launch_screen']:
-        print('Error: no \'default\' field for \'launch_screen\'.')
-        sys.exit(1)
-      default = self.data_src['launch_screen']['default']
-      if 'image' not in default:
-        print('Error: no \'image\' field for \'launch_screen.default\'.')
-        sys.exit(1)
-      ret_dict['launch_screen_img'] = default['image']
+      self.ParseLaunchScreen(ret_dict, 'default')
+      self.ParseLaunchScreen(ret_dict, 'portrait')
+      self.ParseLaunchScreen(ret_dict, 'landscape')
     return ret_dict
 
+  def ParseLaunchScreen(self, ret_dict, orientation):
+    if orientation in self.data_src['launch_screen']:
+      sub_dict = self.data_src['launch_screen'][orientation]
+      if 'background_color' in sub_dict:
+        ret_dict['launch_screen_background_color_' + orientation] = (
+            sub_dict['background_color'])
+      if 'background_image' in sub_dict:
+        ret_dict['launch_screen_background_image_' + orientation] = (
+            sub_dict['background_image'])
+      if 'image' in sub_dict:
+        ret_dict['launch_screen_image_' + orientation] = (
+            sub_dict['image'])
+      if 'image_border' in sub_dict:
+        ret_dict['launch_screen_image_border_' + orientation] = (
+            sub_dict['image_border'])
+
   def ShowItems(self):
     """Show the processed results, it is used for command-line
     internal debugging."""
@@ -164,7 +174,30 @@ class ManifestJsonParser(object):
     print("required_version: %s" % self.GetRequiredVersion())
     print("plugins: %s" % self.GetPlugins())
     print("fullscreen: %s" % self.GetFullScreenFlag())
-    print('launch_screen.default.image: %s' % self.GetLaunchScreenImg())
+    print('launch_screen.default.background_color: %s' %
+        self.GetLaunchScreenBackgroundColor('default'))
+    print('launch_screen.default.background_image: %s' %
+        self.GetLaunchScreenBackgroundImage('default'))
+    print('launch_screen.default.image: %s' %
+        self.GetLaunchScreenImage('default'))
+    print('launch_screen.default.image_border: %s' %
+        self.GetLaunchScreenImageBorder('default'))
+    print('launch_screen.portrait.background_color: %s' %
+        self.GetLaunchScreenBackgroundColor('portrait'))
+    print('launch_screen.portrait.background_image: %s' %
+        self.GetLaunchScreenBackgroundImage('portrait'))
+    print('launch_screen.portrait.image: %s' %
+        self.GetLaunchScreenImage('portrait'))
+    print('launch_screen.portrait.image_border: %s' %
+        self.GetLaunchScreenImageBorder('portrait'))
+    print('launch_screen.landscape.background_color: %s' %
+        self.GetLaunchScreenBackgroundColor('landscape'))
+    print('launch_screen.landscape.background_image: %s' %
+        self.GetLaunchScreenBackgroundImage('landscape'))
+    print('launch_screen.landscape.image: %s' %
+        self.GetLaunchScreenImage('landscape'))
+    print('launch_screen.landscape.image_border: %s' %
+        self.GetLaunchScreenImageBorder('landscape'))
 
 
   def GetAppName(self):
@@ -211,9 +244,33 @@ class ManifestJsonParser(object):
     """Return the set fullscreen flag of the application."""
     return self.ret_dict['fullscreen']
 
-  def GetLaunchScreenImg(self):
-    """Return the default img for launch_screen."""
-    return self.ret_dict['launch_screen_img']
+  def GetLaunchScreenBackgroundColor(self, orientation):
+    """Return the background color for launch_screen."""
+    if 'launch_screen_background_color_' + orientation in self.ret_dict:
+      return self.ret_dict['launch_screen_background_color_' + orientation]
+    else:
+      return ''
+
+  def GetLaunchScreenBackgroundImage(self, orientation):
+    """Return the background image for launch_screen."""
+    if 'launch_screen_background_image_' + orientation in self.ret_dict:
+      return self.ret_dict['launch_screen_background_image_' + orientation]
+    else:
+      return ''
+
+  def GetLaunchScreenImage(self, orientation):
+    """Return the image for launch_screen."""
+    if 'launch_screen_image_' + orientation in self.ret_dict:
+      return self.ret_dict['launch_screen_image_' + orientation]
+    else:
+      return ''
+
+  def GetLaunchScreenImageBorder(self, orientation):
+    """Return the image border for launch_screen."""
+    if 'launch_screen_image_border_' + orientation in self.ret_dict:
+      return self.ret_dict['launch_screen_image_border_' + orientation]
+    else:
+      return ''
 
 
 def main(argv):
index e9989ee..8bd625c 100644 (file)
 #include "xwalk/runtime/browser/xwalk_runner.h"
 #include "xwalk/runtime/common/xwalk_common_messages.h"
 
+#if defined(OS_TIZEN)
+#include "xwalk/runtime/browser/ui/native_app_window.h"
+#endif
+
+#if defined(USE_OZONE) && defined(OS_TIZEN)
+#include "base/message_loop/message_pump_ozone.h"
+#include "content/public/browser/render_view_host.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#include "xwalk/application/common/manifest_handlers/tizen_setting_handler.h"
+#endif
+
+#if defined(OS_TIZEN)
+#include "xwalk/application/common/manifest_handlers/navigation_handler.h"
+#endif
+
 namespace xwalk {
 
 namespace keys = application_manifest_keys;
@@ -82,13 +99,20 @@ Application::Application(
       observer_(observer),
       entry_point_used_(Default),
       termination_mode_used_(Normal),
-      weak_factory_(this) {
+      weak_factory_(this),
+      is_security_mode_(false) {
   DCHECK(runtime_context_);
   DCHECK(application_data_);
   DCHECK(observer_);
+#if defined(USE_OZONE) && defined(OS_TIZEN)
+  base::MessagePumpOzone::Current()->AddObserver(this);
+#endif
 }
 
 Application::~Application() {
+#if defined(USE_OZONE) && defined(OS_TIZEN)
+  base::MessagePumpOzone::Current()->RemoveObserver(this);
+#endif
   Terminate(Immediate);
 }
 
@@ -99,7 +123,7 @@ bool Application::Launch(const LaunchParams& launch_params) {
     return false;
   }
 
-  GURL url = GetURLForLaunch(launch_params, &entry_point_used_);
+  GURL url = GetStartURL(launch_params, &entry_point_used_);
   if (!url.is_valid())
     return false;
 
@@ -109,16 +133,23 @@ bool Application::Launch(const LaunchParams& launch_params) {
   if (entry_point_used_ != AppMainKey) {
     NativeAppWindow::CreateParams params;
     params.net_wm_pid = launch_params.launcher_pid;
-    params.state = launch_params.window_state;
-
+    params.state = GetWindowShowState(launch_params);
     main_runtime_->AttachWindow(params);
   }
 
   return true;
 }
 
-GURL Application::GetURLForLaunch(const LaunchParams& params,
+GURL Application::GetStartURL(const LaunchParams& params,
                                   LaunchEntryPoint* used) {
+  if (params.entry_points & URLKey) {
+    GURL url = GetURLFromURLKey();
+    if (url.is_valid()) {
+      *used = URLKey;
+      return url;
+    }
+  }
+
   if (params.entry_points & AppMainKey) {
     GURL url = GetURLFromAppMainKey();
     if (url.is_valid()) {
@@ -135,13 +166,6 @@ GURL Application::GetURLForLaunch(const LaunchParams& params,
     }
   }
 
-  if (params.entry_points & URLKey) {
-    GURL url = GetURLFromURLKey();
-    if (url.is_valid()) {
-      *used = URLKey;
-      return url;
-    }
-  }
   LOG(WARNING) << "Failed to find a valid launch URL for the app.";
   return GURL();
 }
@@ -156,6 +180,23 @@ GURL Application::GetURLFromAppMainKey() {
   return main_info->GetMainURL();
 }
 
+ui::WindowShowState Application::GetWindowShowState(
+    const LaunchParams& params) {
+  if (params.force_fullscreen)
+    return ui::SHOW_STATE_FULLSCREEN;
+
+  const Manifest* manifest = application_data_->GetManifest();
+  std::string display_string;
+  if (manifest->GetString(keys::kDisplay, &display_string)) {
+    // FIXME: ATM only 'fullscreen' and 'standalone' (which is fallback value)
+    // values are supported.
+    if (display_string.find("fullscreen") != std::string::npos)
+      return ui::SHOW_STATE_FULLSCREEN;
+  }
+
+  return ui::SHOW_STATE_DEFAULT;
+}
+
 GURL Application::GetURLFromLocalPathKey() {
   const Manifest* manifest = application_data_->GetManifest();
   std::string entry_page;
@@ -220,6 +261,17 @@ void Application::Terminate(TerminationMode mode) {
                 std::mem_fun(&Runtime::Close));
 }
 
+#if defined(OS_TIZEN)
+void Application::Hide() {
+  DCHECK(runtimes_.size());
+  std::set<Runtime*>::iterator it = runtimes_.begin();
+  for (; it != runtimes_.end(); ++it) {
+    if ((*it)->window())
+      (*it)->window()->Hide();
+  }
+}
+#endif
+
 Runtime* Application::GetMainDocumentRuntime() const {
   return HasMainDocument() ? main_runtime_ : NULL;
 }
@@ -393,19 +445,43 @@ bool Application::SetPermission(PermissionType type,
 void Application::InitSecurityPolicy() {
   if (application_data_->GetPackageType() != Manifest::TYPE_WGT)
     return;
-  const WARPInfo* info = static_cast<WARPInfo*>(
-      application_data_->GetManifestData(widget_keys::kAccessKey));
-  if (!info
+
 #if defined(OS_TIZEN)
-      // On Tizen, CSP mode has higher priority, and WARP will be disabled
-      // if the application is under CSP mode.
-      || application_data_->HasCSPDefined()
+  // On Tizen, CSP mode has higher priority, and WARP will be disabled
+  // if the application is under CSP mode.
+  if (application_data_->HasCSPDefined()) {
+    // Always enable security mode when under CSP mode.
+    is_security_mode_ = true;
+    NavigationInfo* info = static_cast<NavigationInfo*>(
+        application_data_->GetManifestData(widget_keys::kAllowNavigationKey));
+    if (info) {
+      const std::vector<std::string>& allowed_list = info->GetAllowedDomains();
+      for (std::vector<std::string>::const_iterator it = allowed_list.begin();
+           it != allowed_list.end(); ++it) {
+        // If the policy start with "*.", like this: *.domain,
+        // means that can access to all subdomains for 'domain',
+        // otherwise, the host of request url should exactly the same
+        // as policy.
+        bool subdomains = ((*it).find("*.") == 0);
+        std::string host = subdomains ? (*it).substr(2) : (*it);
+        AddSecurityPolicy(GURL("http://" + host), subdomains);
+        AddSecurityPolicy(GURL("https://" + host), subdomains);
+      }
+    }
+    GetHost(main_runtime_)->Send(
+        new ViewMsg_EnableSecurityMode(
+            ApplicationData::GetBaseURLFromApplicationId(id()),
+            SecurityPolicy::CSP));
+    return;
+  }
 #endif
-      )
+  const WARPInfo* info = static_cast<WARPInfo*>(
+      application_data_->GetManifestData(widget_keys::kAccessKey));
+  // FIXME(xinchao): Need to enable WARP mode by default.
+  if (!info)
     return;
-  GURL app_url = application_data_->URL();
+
   const base::ListValue* whitelist = info->GetWARP();
-  bool enable_warp_mode = true;
   for (base::ListValue::const_iterator it = whitelist->begin();
        it != whitelist->end(); ++it) {
     base::DictionaryValue* value = NULL;
@@ -415,7 +491,7 @@ void Application::InitSecurityPolicy() {
         dest.empty())
       continue;
     if (dest == "*") {
-      enable_warp_mode = false;
+      is_security_mode_ = false;
       break;
     }
 
@@ -423,16 +499,83 @@ void Application::InitSecurityPolicy() {
     // The default subdomains attrubute should be "false".
     std::string subdomains = "false";
     value->GetString(widget_keys::kAccessSubdomainsKey, &subdomains);
-    GetHost(main_runtime_)->Send(
-        new ViewMsg_SetAccessWhiteList(
-            app_url, dest_url, (subdomains == "true")));
+    AddSecurityPolicy(dest_url, (subdomains == "true"));
+    is_security_mode_ = true;
   }
-  if (enable_warp_mode)
+  if (is_security_mode_)
     GetHost(main_runtime_)->Send(
-        new ViewMsg_EnableWarpMode(
-            ApplicationData::GetBaseURLFromApplicationId(
-                application_data_->ID())));
+        new ViewMsg_EnableSecurityMode(
+            ApplicationData::GetBaseURLFromApplicationId(id()),
+            SecurityPolicy::WARP));
+}
+
+void Application::AddSecurityPolicy(const GURL& url, bool subdomains) {
+  GURL app_url = application_data_->URL();
+  GetHost(main_runtime_)->Send(
+      new ViewMsg_SetAccessWhiteList(
+          app_url, url, subdomains));
+  security_policy_.push_back(new SecurityPolicy(url, subdomains));
+}
+
+bool Application::CanRequestURL(const GURL& url) const {
+  if (!is_security_mode_)
+    return true;
+
+  // Only WGT package need to check the url request permission.
+  if (application_data_->GetPackageType() != Manifest::TYPE_WGT)
+    return true;
+
+  // Always can request itself resources.
+  if (url.SchemeIs(application::kApplicationScheme) &&
+      url.host() == id())
+    return true;
+
+  for (int i = 0; i < security_policy_.size(); ++i) {
+    const GURL& policy = security_policy_[i]->url();
+    bool subdomains = security_policy_[i]->subdomains();
+    bool is_host_matched = subdomains ?
+        url.DomainIs(policy.host().c_str()) : url.host() == policy.host();
+    if (url.scheme() == policy.scheme() && is_host_matched)
+      return true;
+  }
+  return false;
+}
+
+#if defined(USE_OZONE) && defined(OS_TIZEN)
+base::EventStatus Application::WillProcessEvent(
+    const base::NativeEvent& event) {
+  return base::EVENT_CONTINUE;
 }
 
+void Application::DidProcessEvent(
+    const base::NativeEvent& event) {
+  ui::Event* eve = static_cast<ui::Event*>(event);
+  if (!eve->IsKeyEvent() || eve->type() != ui::ET_KEY_PRESSED)
+    return;
+
+  ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(eve);
+
+  // FIXME: Most Wayland devices don't have similar hardware button for 'back'
+  // and 'memu' as Tizen Mobile, even that hardare buttons could be different
+  // across different kinds of Wayland platforms.
+  // Here use external keyboard button 'Backspace' & 'HOME' to emulate 'back'
+  // and 'menu' key. Should change this if there is customized key binding.
+  if (key_event->key_code() != ui::VKEY_BACK &&
+      key_event->key_code() != ui::VKEY_HOME)
+    return;
+
+  TizenSettingInfo* info = static_cast<TizenSettingInfo*>(
+      data()->GetManifestData(widget_keys::kTizenSettingKey));
+  if (info && !info->hwkey_enabled())
+    return;
+
+  for (std::set<xwalk::Runtime*>::iterator it = runtimes_.begin();
+      it != runtimes_.end(); ++it) {
+    (*it)->web_contents()->GetRenderViewHost()->Send(new ViewMsg_HWKeyPressed(
+        (*it)->web_contents()->GetRoutingID(), key_event->key_code()));
+  }
+}
+#endif
+
 }  // namespace application
 }  // namespace xwalk
index f928494..4de28db 100644 (file)
@@ -8,6 +8,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "ui/base/ui_base_types.h"
 #include "xwalk/application/browser/event_observer.h"
 #include "xwalk/application/common/application_data.h"
+#include "xwalk/application/common/security_policy.h"
 #include "xwalk/runtime/browser/runtime.h"
 
+#if defined(USE_OZONE) && defined(OS_TIZEN)
+#include "base/message_loop/message_pump_observer.h"
+#endif
+
 namespace xwalk {
 
 class RuntimeContext;
@@ -27,6 +33,7 @@ namespace application {
 
 class ApplicationHost;
 class Manifest;
+class SecurityPolicy;
 
 // The Application class is representing an active (running) application.
 // Application instances are owned by ApplicationService.
@@ -34,7 +41,12 @@ class Manifest;
 // terminated.
 // There's one-to-one correspondence between Application and Render Process
 // Host, obtained from its "runtimes" (pages).
-class Application : public Runtime::Observer {
+class Application
+  :
+#if defined(USE_OZONE) && defined(OS_TIZEN)
+  public base::MessagePumpObserver,
+#endif
+  public Runtime::Observer {
  public:
   virtual ~Application();
 
@@ -52,12 +64,8 @@ class Application : public Runtime::Observer {
   enum LaunchEntryPoint {
     AppMainKey = 1 << 0,  // app.main
     LaunchLocalPathKey = 1 << 1,  // app.launch.local_path
-    // NOTE: The following key is only used for "dummy" hosted apps,
-    // which can be using any arbitrary URL, incl. remote ones.
-    // For now this should be disabled for all other cases as this will
-    // require special care with permissions etc.
     URLKey = 1 << 2,  // url
-    Default = AppMainKey | LaunchLocalPathKey
+    Default = AppMainKey | LaunchLocalPathKey | URLKey
   };
   typedef unsigned LaunchEntryPoints;
 
@@ -65,7 +73,7 @@ class Application : public Runtime::Observer {
     LaunchParams() :
         entry_points(Default),
         launcher_pid(0),
-        window_state(ui::SHOW_STATE_DEFAULT) {}
+        force_fullscreen(false) {}
 
     LaunchEntryPoints entry_points;
 
@@ -73,8 +81,7 @@ class Application : public Runtime::Observer {
     // process.
     int32 launcher_pid;
 
-    // Sets the initial state for the application windows.
-    ui::WindowShowState window_state;
+    bool force_fullscreen;
   };
 
   // Closes all the application's runtimes (application pages).
@@ -90,6 +97,10 @@ class Application : public Runtime::Observer {
   };
   void Terminate(TerminationMode = Normal);
 
+#if defined(OS_TIZEN)
+  void Hide();
+#endif
+
   // Returns Runtime (application page) containing the application's
   // 'main document'. The main document is the main entry point of
   // the application to the system. This method will return 'NULL'
@@ -127,6 +138,7 @@ class Application : public Runtime::Observer {
   bool SetPermission(PermissionType type,
                      const std::string& permission_name,
                      StoredPermission perm);
+  bool CanRequestURL(const GURL& url) const;
 
  private:
   bool HasMainDocument() const;
@@ -143,7 +155,8 @@ class Application : public Runtime::Observer {
 
   // Try to extract the URL from different possible keys for entry points in the
   // manifest, returns it and the entry point used.
-  GURL GetURLForLaunch(const LaunchParams& params, LaunchEntryPoint* used);
+  GURL GetStartURL(const LaunchParams& params, LaunchEntryPoint* used);
+  ui::WindowShowState GetWindowShowState(const LaunchParams& params);
 
   GURL GetURLFromAppMainKey();
   GURL GetURLFromLocalPathKey();
@@ -156,6 +169,13 @@ class Application : public Runtime::Observer {
   bool IsTerminating() const { return finish_observer_; }
 
   void InitSecurityPolicy();
+  void AddSecurityPolicy(const GURL& url, bool subdomains);
+
+#if defined(USE_OZONE) && defined(OS_TIZEN)
+  virtual base::EventStatus WillProcessEvent(
+      const base::NativeEvent& event) OVERRIDE;
+  virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
+#endif
 
   RuntimeContext* runtime_context_;
   const scoped_refptr<ApplicationData> application_data_;
@@ -170,6 +190,9 @@ class Application : public Runtime::Observer {
   std::map<std::string, std::string> name_perm_map_;
   // Application's session permissions.
   StoredPermissionMap permission_map_;
+  // Security policy set.
+  ScopedVector<SecurityPolicy> security_policy_;
+  bool is_security_mode_;
 
   DISALLOW_COPY_AND_ASSIGN(Application);
 };
index 0a8a360..78a252e 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <map>
+#include <list>
 #include <string>
 #include <utility>
 #include <vector>
@@ -152,6 +153,7 @@ class URLRequestApplicationJob : public net::URLRequestFileJob {
       const base::FilePath& directory_path,
       const base::FilePath& relative_path,
       const std::string& content_security_policy,
+      const std::list<std::string>& locales,
       bool is_authority_match)
       : net::URLRequestFileJob(
           request, network_delegate, base::FilePath(), file_task_runner),
@@ -159,6 +161,7 @@ class URLRequestApplicationJob : public net::URLRequestFileJob {
         content_security_policy_(content_security_policy),
         is_authority_match_(is_authority_match),
         resource_(application_id, directory_path, relative_path),
+        locales_(locales),
         weak_factory_(this) {
   }
 
@@ -175,6 +178,7 @@ class URLRequestApplicationJob : public net::URLRequestFileJob {
   virtual void Start() OVERRIDE {
     base::FilePath* read_file_path = new base::FilePath;
 
+    resource_.SetLocales(locales_);
     bool posted = base::WorkerPool::PostTaskAndReply(
         FROM_HERE,
         base::Bind(&ReadResourceFilePath, resource_,
@@ -202,6 +206,7 @@ class URLRequestApplicationJob : public net::URLRequestFileJob {
   std::string content_security_policy_;
   bool is_authority_match_;
   ApplicationResource resource_;
+  std::list<std::string> locales_;
   base::WeakPtrFactory<URLRequestApplicationJob> weak_factory_;
 };
 
@@ -297,6 +302,8 @@ ApplicationProtocolHandler::MaybeCreateJob(
                                         content_security_policy);
   }
 
+  std::list<std::string> locales;
+  // FIXME(Xinchao): Get the user agent locales into |locales|.
   return new URLRequestApplicationJob(
       request,
       network_delegate,
@@ -307,6 +314,7 @@ ApplicationProtocolHandler::MaybeCreateJob(
       directory_path,
       relative_path,
       content_security_policy,
+      locales,
       application);
 }
 
index 1469114..b9a8411 100644 (file)
@@ -38,21 +38,21 @@ namespace application {
 
 namespace {
 
-void CloseMessageLoop() {
-  // FIXME: Quit message loop here at present. This should go away once
-  // we have Application in place.
-  base::MessageLoop::current()->QuitWhenIdle();
-}
-
 void WaitForEventAndClose(
-    const std::string& app_id, const std::string& event_name,
+    const std::string& app_id,
+    const std::string& event_name,
+    ApplicationService* application_service,
     ApplicationEventManager* event_manager) {
+
   class CloseOnEventArrived : public EventObserver {
    public:
-    static CloseOnEventArrived* Create(const std::string& event_name,
-        ApplicationEventManager* event_manager) {
-      return new CloseOnEventArrived(event_name, event_manager);
-    }
+    CloseOnEventArrived(
+        const std::string& event_name,
+        ApplicationService* application_service,
+        ApplicationEventManager* event_manager)
+        : EventObserver(event_manager),
+          event_name_(event_name),
+          application_service_(application_service) {}
 
     virtual void Observe(
         const std::string& app_id,
@@ -62,41 +62,42 @@ void WaitForEventAndClose(
       event->args()->GetString(0, &ack_event_name);
       if (ack_event_name != event_name_)
         return;
-      CloseMessageLoop();
+
+      if (Application* app = application_service_->GetApplicationByID(app_id))
+        app->Terminate(Application::Immediate);
+
       delete this;
     }
 
    private:
-    CloseOnEventArrived(
-        const std::string& event_name,
-        ApplicationEventManager* event_manager)
-        : EventObserver(event_manager),
-          event_name_(event_name) {}
-
     std::string event_name_;
+    ApplicationService* application_service_;
   };
 
   DCHECK(event_manager);
   CloseOnEventArrived* observer =
-      CloseOnEventArrived::Create(event_name, event_manager);
+      new CloseOnEventArrived(event_name, application_service, event_manager);
   event_manager->AttachObserver(app_id,
       kOnJavaScriptEventAck, observer);
 }
 
 void WaitForFinishLoad(
-    scoped_refptr<ApplicationData> application,
+    const std::string& app_id,
+    ApplicationService* application_service,
     ApplicationEventManager* event_manager,
     content::WebContents* contents) {
   class CloseAfterLoadObserver : public content::WebContentsObserver {
    public:
     CloseAfterLoadObserver(
-        scoped_refptr<ApplicationData> application,
+        const std::string& app_id,
+        ApplicationService* application_service,
         ApplicationEventManager* event_manager,
         content::WebContents* contents)
         : content::WebContentsObserver(contents),
-          application_(application),
+          id_(app_id),
+          application_service_(application_service),
           event_manager_(event_manager) {
-      DCHECK(application_);
+      DCHECK(application_service_);
       DCHECK(event_manager_);
     }
 
@@ -105,45 +106,53 @@ void WaitForFinishLoad(
         const GURL& validate_url,
         bool is_main_frame,
         content::RenderViewHost* render_view_host) OVERRIDE {
-      if (!IsEventHandlerRegistered(kOnInstalled)) {
-        CloseMessageLoop();
+      Application* app = application_service_->GetApplicationByID(id_);
+      if (!app) {
+        delete this;
+        return;
+      }
+
+      if (!IsEventHandlerRegistered(app->data(), kOnInstalled)) {
+          app->Terminate(Application::Immediate);
       } else {
         scoped_ptr<base::ListValue> event_args(new base::ListValue);
         scoped_refptr<Event> event =
-            Event::CreateEvent(
-                kOnInstalled, event_args.Pass());
-        event_manager_->SendEvent(application_->ID(), event);
+            Event::CreateEvent(kOnInstalled, event_args.Pass());
+        event_manager_->SendEvent(id_, event);
 
         WaitForEventAndClose(
-            application_->ID(), event->name(), event_manager_);
+            id_, event->name(), application_service_, event_manager_);
       }
       delete this;
     }
 
    private:
-    bool IsEventHandlerRegistered(const std::string& event_name) const {
-      const std::set<std::string>& events = application_->GetEvents();
+    bool IsEventHandlerRegistered(scoped_refptr<ApplicationData> app_data,
+                                  const std::string& event_name) const {
+      const std::set<std::string>& events = app_data->GetEvents();
       return events.find(event_name) != events.end();
     }
 
-    scoped_refptr<ApplicationData> application_;
+    std::string id_;
+    ApplicationService* application_service_;
     ApplicationEventManager* event_manager_;
   };
 
   // This object is self-destroyed when an event occurs.
-  new CloseAfterLoadObserver(application, event_manager, contents);
+  new CloseAfterLoadObserver(
+      app_id, application_service, event_manager, contents);
 }
 
 void SaveSystemEventsInfo(
-    ApplicationService* application_service,
     scoped_refptr<ApplicationData> application_data,
+    ApplicationService* application_service,
     ApplicationEventManager* event_manager) {
   // We need to run main document after installation in order to
   // register system events.
   if (application_data->HasMainDocument()) {
     if (Application* application =
         application_service->Launch(application_data->ID())) {
-      WaitForFinishLoad(application->data(), event_manager,
+      WaitForFinishLoad(application->id(), application_service, event_manager,
                         application->GetMainDocumentRuntime()->web_contents());
     }
   }
@@ -299,7 +308,7 @@ bool ApplicationService::Install(const base::FilePath& path, std::string* id) {
             << " successfully.";
   *id = application_data->ID();
 
-  SaveSystemEventsInfo(this, application_data, event_manager_);
+  SaveSystemEventsInfo(application_data, this, event_manager_);
 
   FOR_EACH_OBSERVER(Observer, observers_,
                     OnApplicationInstalled(application_data->ID()));
@@ -420,7 +429,7 @@ bool ApplicationService::Update(const std::string& id,
 #endif
   base::DeleteFile(tmp_dir, true);
 
-  SaveSystemEventsInfo(this, new_application, event_manager_);
+  SaveSystemEventsInfo(new_application, this, event_manager_);
 
   FOR_EACH_OBSERVER(Observer, observers_,
                     OnApplicationUpdated(app_id));
@@ -483,6 +492,28 @@ bool ApplicationService::Uninstall(const std::string& id) {
   return result;
 }
 
+bool ApplicationService::ChangeLocale(const std::string& locale) {
+  const ApplicationData::ApplicationDataMap& apps =
+      application_storage_->GetInstalledApplications();
+  ApplicationData::ApplicationDataMap::const_iterator it;
+  for (it = apps.begin(); it != apps.end(); ++it) {
+    base::string16 error;
+    std::string old_name = it->second->Name();
+    if (!it->second->SetApplicationLocale(locale, &error)) {
+      LOG(ERROR) << "Error when set locale " << locale
+                 << " to application " << it->second->ID()
+                 << "error : " << error;
+    }
+    if (old_name != it->second->Name()) {
+      // After we has changed the application locale, we might get a new name in
+      // the new locale, so call all observer for this event.
+      FOR_EACH_OBSERVER(
+          Observer, observers_,
+          OnApplicationNameChanged(it->second->ID(), it->second->Name()));
+    }
+  }
+}
+
 Application* ApplicationService::Launch(
     scoped_refptr<ApplicationData> application_data,
     const Application::LaunchParams& launch_params) {
@@ -611,7 +642,8 @@ void ApplicationService::OnApplicationTerminated(
   FOR_EACH_OBSERVER(Observer, observers_,
                     WillDestroyApplication(application));
   applications_.erase(found);
-  if (applications_.empty()) {
+  if (!XWalkRunner::GetInstance()->is_running_as_service() &&
+      applications_.empty()) {
     base::MessageLoop::current()->PostTask(
             FROM_HERE, base::MessageLoop::QuitClosure());
   }
index bed7711..23e30a1 100644 (file)
@@ -35,6 +35,10 @@ class ApplicationService : public Application::Observer {
     virtual void OnApplicationInstalled(const std::string& app_id) {}
     virtual void OnApplicationUninstalled(const std::string& app_id) {}
     virtual void OnApplicationUpdated(const std::string& app_id) {}
+    // When we change the application locale, we might get a new name in
+    // the new locale.
+    virtual void OnApplicationNameChanged(const std::string& app_id,
+                                          const std::string& app_name) {}
 
     virtual void DidLaunchApplication(Application* app) {}
     virtual void WillDestroyApplication(Application* app) {}
@@ -50,6 +54,7 @@ class ApplicationService : public Application::Observer {
   bool Install(const base::FilePath& path, std::string* id);
   bool Uninstall(const std::string& id);
   bool Update(const std::string& id, const base::FilePath& path);
+  bool ChangeLocale(const std::string& locale);
 
   Application* Launch(scoped_refptr<ApplicationData> application_data,
                       const Application::LaunchParams& launch_params);
index 15a311a..cb1ef92 100644 (file)
@@ -123,8 +123,7 @@ bool ApplicationSystem::LaunchWithCommandLineParam(
         kOnLaunched, scoped_ptr<base::ListValue>(new base::ListValue));
 
   Application::LaunchParams launch_params;
-  if (cmd_line.HasSwitch(switches::kFullscreen))
-    launch_params.window_state = ui::SHOW_STATE_FULLSCREEN;
+  launch_params.force_fullscreen = cmd_line.HasSwitch(switches::kFullscreen);
 
   if (application_service_->Launch(param, launch_params)) {
     return true;
@@ -164,8 +163,7 @@ bool ApplicationSystem::LaunchWithCommandLineParam<GURL>(
   }
 
   Application::LaunchParams launch_params;
-  if (cmd_line.HasSwitch(switches::kFullscreen))
-    launch_params.window_state = ui::SHOW_STATE_FULLSCREEN;
+  launch_params.force_fullscreen = cmd_line.HasSwitch(switches::kFullscreen);
   launch_params.entry_points = Application::URLKey;
 
   return !!application_service_->Launch(application_data, launch_params);
index 52f305a..735bb67 100644 (file)
@@ -9,6 +9,7 @@
 #include <unistd.h>
 #include <pkgmgr/pkgmgr_parser.h>
 #include <algorithm>
+#include <map>
 #include <string>
 #include "base/file_util.h"
 #include "base/files/file_enumerator.h"
@@ -18,6 +19,8 @@
 #include "base/process/launch.h"
 #include "third_party/libxml/chromium/libxml_utils.h"
 #include "xwalk/application/common/application_data.h"
+#include "xwalk/application/common/application_manifest_constants.h"
+#include "xwalk/application/common/manifest_handlers/tizen_metadata_handler.h"
 #include "xwalk/application/browser/application_storage.h"
 #include "xwalk/application/browser/installer/tizen/packageinfo_constants.h"
 
@@ -25,6 +28,8 @@ namespace info = xwalk::application_packageinfo_constants;
 
 namespace {
 
+namespace widget_keys = xwalk::application_widget_keys;
+
 const base::FilePath kPkgHelper("/usr/bin/xwalk-pkg-helper");
 
 const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
@@ -57,6 +62,22 @@ class FileDeleter {
   bool recursive_;
 };
 
+void WriteMetaDataElement(
+    XmlWriter& writer,
+    xwalk::application::TizenMetaDataInfo* info) {
+  if (!info)
+    return;
+
+  const std::map<std::string, std::string>& metadata = info->metadata();
+  std::map<std::string, std::string>::const_iterator it;
+  for (it = metadata.begin(); it != metadata.end(); ++it) {
+    writer.StartElement("metadata");
+    writer.AddAttribute("key", it->first);
+    writer.AddAttribute("value", it->second);
+    writer.EndElement();
+  }
+}
+
 bool GeneratePkgInfoXml(xwalk::application::ApplicationData* application,
                         const std::string& icon_name,
                         const base::FilePath& app_dir,
@@ -89,6 +110,11 @@ bool GeneratePkgInfoXml(xwalk::application::ApplicationData* application,
   xml_writer.AddAttribute("taskmanage", "true");
   xml_writer.WriteElement("label", application->Name());
 
+  xwalk::application::TizenMetaDataInfo* info =
+      static_cast<xwalk::application::TizenMetaDataInfo*>(
+      application->GetManifestData(widget_keys::kTizenMetaDataKey));
+  WriteMetaDataElement(xml_writer, info);
+
   if (icon_name.empty())
     xml_writer.WriteElement("icon", info::kDefaultIconName);
   else
index b856e46..cf067f6 100644 (file)
@@ -42,6 +42,12 @@ InstalledApplicationObject::InstalledApplicationObject(
   properties()->Set(kInstalledApplicationDBusInterface, "Name", name.Pass());
 }
 
+void InstalledApplicationObject::OnApplicationNameChanged(
+    const std::string& app_name) {
+  scoped_ptr<base::Value> name(base::Value::CreateStringValue(app_name));
+  properties()->Set(kInstalledApplicationDBusInterface, "Name", name.Pass());
+}
+
 void InstalledApplicationObject::ExportUninstallMethod(
     dbus::ExportedObject::MethodCallCallback method_call_callback,
     dbus::ExportedObject::OnExportedCallback on_exported_callback) {
index 742d9c2..9c8af4b 100644 (file)
@@ -26,6 +26,7 @@ class InstalledApplicationObject : public dbus::ManagedObject {
       scoped_refptr<dbus::Bus> bus, const dbus::ObjectPath& path,
       const ApplicationData* app);
 
+  void OnApplicationNameChanged(const std::string& app_name);
   // Set the callback used when the Uninstall() method is called in an
   // ApplicationObject.
   void ExportUninstallMethod(
index 02ce18f..0e0a7ad 100644 (file)
@@ -72,6 +72,14 @@ void InstalledApplicationsManager::OnApplicationUninstalled(
   adaptor_.RemoveManagedObject(GetInstalledPathForAppID(app_id));
 }
 
+void InstalledApplicationsManager::OnApplicationNameChanged(
+    const std::string& app_id, const std::string& app_name) {
+  InstalledApplicationObject* object =
+      static_cast<InstalledApplicationObject*>(
+          adaptor_.GetManagedObject(GetInstalledPathForAppID(app_id)));
+  object->OnApplicationNameChanged(app_name);
+}
+
 void InstalledApplicationsManager::AddInitialObjects() {
   const ApplicationData::ApplicationDataMap& apps =
       app_storage_->GetInstalledApplications();
index 0896154..b294e43 100644 (file)
@@ -34,6 +34,8 @@ class InstalledApplicationsManager : public ApplicationService::Observer {
   // ApplicationService::Observer implementation.
   void virtual OnApplicationInstalled(const std::string& app_id) OVERRIDE;
   void virtual OnApplicationUninstalled(const std::string& app_id) OVERRIDE;
+  void virtual OnApplicationNameChanged(const std::string& app_id,
+                                        const std::string& app_name) OVERRIDE;
 
   void AddInitialObjects();
   void AddObject(scoped_refptr<const ApplicationData> app);
index 2aebe15..b53b19d 100644 (file)
@@ -74,6 +74,15 @@ RunningApplicationObject::RunningApplicationObject(
                  base::Unretained(this)),
       base::Bind(&RunningApplicationObject::OnExported,
                  base::Unretained(this)));
+
+#if defined(OS_TIZEN)
+  dbus_object()->ExportMethod(
+      kRunningApplicationDBusInterface, "Hide",
+      base::Bind(&RunningApplicationObject::OnHide,
+                 base::Unretained(this)),
+      base::Bind(&RunningApplicationObject::OnExported,
+                 base::Unretained(this)));
+#endif
 }
 
 RunningApplicationObject::~RunningApplicationObject() {
@@ -135,6 +144,27 @@ void RunningApplicationObject::OnGetExtensionProcessChannel(
   response_sender.Run(response.Pass());
 }
 
+#if defined(OS_TIZEN)
+void RunningApplicationObject::OnHide(
+    dbus::MethodCall* method_call,
+    dbus::ExportedObject::ResponseSender response_sender) {
+  if (method_call->GetSender() != launcher_name_) {
+    scoped_ptr<dbus::ErrorResponse> error_response =
+        dbus::ErrorResponse::FromMethodCall(method_call,
+                                            kRunningApplicationDBusError,
+                                            "Not permitted");
+    response_sender.Run(error_response.PassAs<dbus::Response>());
+    return;
+  }
+
+  application_->Hide();
+
+  scoped_ptr<dbus::Response> response =
+      dbus::Response::FromMethodCall(method_call);
+  response_sender.Run(response.Pass());
+}
+#endif
+
 void RunningApplicationObject::ListenForOwnerChange() {
   owner_change_callback_ =
       base::Bind(&RunningApplicationObject::OnNameOwnerChanged,
index c67e0bf..02e0812 100644 (file)
@@ -47,6 +47,11 @@ class RunningApplicationObject : public dbus::ManagedObject {
       dbus::MethodCall* method_call,
       dbus::ExportedObject::ResponseSender response_sender);
 
+#if defined(OS_TIZEN)
+  void OnHide(dbus::MethodCall* method_call,
+              dbus::ExportedObject::ResponseSender response_sender);
+#endif
+
   void ListenForOwnerChange();
   void UnlistenForOwnerChange();
   void OnNameOwnerChanged(const std::string& service_owner);
index 5861fd4..6a70625 100644 (file)
@@ -96,8 +96,7 @@ void RunningApplicationsManager::OnLaunch(
 
   Application::LaunchParams params;
   params.launcher_pid = launcher_pid;
-  if (fullscreen)
-    params.window_state = ui::SHOW_STATE_FULLSCREEN;
+  params.force_fullscreen = fullscreen;
 
   Application* application = application_service_->Launch(app_id, params);
   if (!application) {
index aeec0c1..54a6762 100644 (file)
@@ -371,5 +371,15 @@ bool ApplicationData::HasCSPDefined() const {
 }
 #endif
 
+bool ApplicationData::SetApplicationLocale(const std::string& locale,
+                                           base::string16* error) {
+  manifest_->SetSystemLocale(locale);
+  if (!LoadName(error))
+    return false;
+  if (!LoadDescription(error))
+    return false;
+  return true;
+}
+
 }   // namespace application
 }   // namespace xwalk
index 28d732c..b802039 100644 (file)
@@ -138,6 +138,8 @@ class ApplicationData : public base::RefCountedThreadSafe<ApplicationData> {
   bool HasCSPDefined() const;
 #endif
 
+  bool SetApplicationLocale(const std::string& locale, base::string16* error);
+
  private:
   friend class base::RefCountedThreadSafe<ApplicationData>;
   friend class ApplicationStorageImpl;
index 945e77c..40dc276 100644 (file)
@@ -16,6 +16,15 @@ const char kDescriptionKey[] = "description";
 const char kDisplay[] = "display";
 const char kLaunchLocalPathKey[] = "app.launch.local_path";
 const char kLaunchScreen[] = "launch_screen";
+const char kLaunchScreenDefault[] = "launch_screen.default";
+const char kLaunchScreenImageBorderDefault[] =
+    "launch_screen.default.image_border";
+const char kLaunchScreenImageBorderLandscape[] =
+    "launch_screen.landscape.image_border";
+const char kLaunchScreenImageBorderPortrait[] =
+    "launch_screen.portrait.image_border";
+const char kLaunchScreenLandscape[] = "launch_screen.landscape";
+const char kLaunchScreenPortrait[] = "launch_screen.portrait";
 const char kLaunchScreenReadyWhen[] = "launch_screen.ready_when";
 const char kLaunchWebURLKey[] = "app.launch.web_url";
 const char kManifestVersionKey[] = "manifest_version";
@@ -24,6 +33,7 @@ const char kPermissionsKey[] = "permissions";
 const char kURLKey[] = "url";
 const char kVersionKey[] = "version";
 const char kWebURLsKey[] = "app.urls";
+const char kXWalkHostsKey[] = "xwalk_hosts";
 
 #if defined(OS_TIZEN)
 const char kTizenAppIdKey[] = "tizen_app_id";
@@ -35,6 +45,8 @@ const char kIcon128Key[] = "icons.128";
 // manifest keys for widget applications.
 namespace application_widget_keys {
 const char kNamespaceKey[] = "@namespace";
+const char kXmlLangKey[] = "@lang";
+const char kDefaultLocaleKey[] = "widget.@defaultlocale";
 const char kNameKey[] = "widget.name.#text";
 const char kVersionKey[] = "widget.@version";
 const char kWidgetKey[] = "widget";
@@ -75,6 +87,10 @@ const char kCSPReportOnlyKey[] =
     "widget.content-security-policy-report-only.#text";
 const char kTizenSettingKey[] = "widget.setting";
 const char kTizenHardwareKey[] = "widget.setting.@hwkey";
+const char kTizenMetaDataKey[] = "widget.metadata";
+// Child keys inside 'kTizenMetaDataKey'
+const char kTizenMetaDataNameKey[] = "@key";
+const char kTizenMetaDataValueKey[] = "@value";
 #endif
 }  // namespace application_widget_keys
 
index 21daaee..d7aee52 100644 (file)
@@ -18,6 +18,12 @@ namespace application_manifest_keys {
   extern const char kDisplay[];
   extern const char kLaunchLocalPathKey[];
   extern const char kLaunchScreen[];
+  extern const char kLaunchScreenDefault[];
+  extern const char kLaunchScreenImageBorderDefault[];
+  extern const char kLaunchScreenImageBorderLandscape[];
+  extern const char kLaunchScreenImageBorderPortrait[];
+  extern const char kLaunchScreenLandscape[];
+  extern const char kLaunchScreenPortrait[];
   extern const char kLaunchScreenReadyWhen[];
   extern const char kLaunchWebURLKey[];
   extern const char kManifestVersionKey[];
@@ -26,6 +32,7 @@ namespace application_manifest_keys {
   extern const char kURLKey[];
   extern const char kVersionKey[];
   extern const char kWebURLsKey[];
+  extern const char kXWalkHostsKey[];
 
 #if defined(OS_TIZEN)
   extern const char kTizenAppIdKey[];
@@ -35,6 +42,8 @@ namespace application_manifest_keys {
 
 namespace application_widget_keys {
   extern const char kNamespaceKey[];
+  extern const char kXmlLangKey[];
+  extern const char kDefaultLocaleKey[];
   extern const char kNameKey[];
   extern const char kLaunchLocalPathKey[];
   extern const char kWebURLsKey[];
@@ -67,6 +76,9 @@ namespace application_widget_keys {
   extern const char kCSPReportOnlyKey[];
   extern const char kTizenSettingKey[];
   extern const char kTizenHardwareKey[];
+  extern const char kTizenMetaDataKey[];
+  extern const char kTizenMetaDataNameKey[];
+  extern const char kTizenMetaDataValueKey[];
 #endif
 }  // namespace application_widget_keys
 
index c959d03..e8d8aea 100644 (file)
 
 namespace xwalk {
 namespace application {
+namespace {
+const base::FilePath::StringType WGT_LOCALE_DIRECTORY =
+    FILE_PATH_LITERAL("locales");
+}  // namespace
 
 ApplicationResource::ApplicationResource() : follow_symlinks_anywhere_(false) {
 }
@@ -41,6 +45,17 @@ const base::FilePath& ApplicationResource::GetFilePath() const {
   if (!full_resource_path_.empty())
     return full_resource_path_;
 
+  for (std::list<std::string>::const_iterator it = locales_.begin();
+       it != locales_.end(); ++it) {
+    full_resource_path_ = GetFilePath(
+        application_root_,
+        base::FilePath(WGT_LOCALE_DIRECTORY)
+        .AppendASCII(*it).Append(relative_path_),
+        follow_symlinks_anywhere_ ?
+        FOLLOW_SYMLINKS_ANYWHERE : SYMLINKS_MUST_RESOLVE_WITHIN_ROOT);
+    if (!full_resource_path_.empty())
+      return full_resource_path_;
+  }
   full_resource_path_ = GetFilePath(
       application_root_, relative_path_,
       follow_symlinks_anywhere_ ?
index acf8531..3293b0d 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef XWALK_APPLICATION_COMMON_APPLICATION_RESOURCE_H_
 #define XWALK_APPLICATION_COMMON_APPLICATION_RESOURCE_H_
 
+#include <list>
 #include <string>
 
 #include "base/files/file_path.h"
@@ -60,6 +61,12 @@ class ApplicationResource {
   const base::FilePath& application_root() const { return application_root_; }
   const base::FilePath& relative_path() const { return relative_path_; }
 
+  // Setters
+  void SetLocales(const std::list<std::string>& locales) {
+    locales_ = locales;
+    full_resource_path_.clear();
+  }
+
   bool empty() const { return application_root().empty(); }
 
   // Unit test helpers.
@@ -83,6 +90,9 @@ class ApplicationResource {
 
   // Full path to application resource. Starts empty.
   mutable base::FilePath full_resource_path_;
+
+  // The User Agent localization information.
+  std::list<std::string> locales_;
 };
 
 }  // namespace application
index 1f529ab..ba9647d 100644 (file)
@@ -4,13 +4,17 @@
 
 #include "xwalk/application/common/manifest.h"
 
+#include <list>
+
 #include "base/basictypes.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "xwalk/application/common/application_manifest_constants.h"
+#include "xwalk/runtime/browser/xwalk_runner.h"
 
 namespace errors = xwalk::application_manifest_errors;
 namespace keys   = xwalk::application_manifest_keys;
@@ -18,11 +22,52 @@ namespace widget_keys = xwalk::application_widget_keys;
 
 namespace xwalk {
 namespace application {
+namespace {
+const char kLocaleUnlocalized[] = "@unlocalized";
+#if defined(OS_TIZEN)
+const char kLocaleAuto[] = "en-gb";
+#else
+const char kLocaleAuto[] = "en-us";
+#endif
+const char kLocaleFirstOne[] = "*";
+
+const char kWidgetNamePath[] = "widget.name";
+const char kWidgetDecriptionPath[] = "widget.description";
+const char kWidgetLicensePath[] = "widget.license";
+
+const char kPathConnectSymbol = '.';
+
+typedef std::list<std::string> List;
+
+std::string GetLocalizedKey(const std::string& key,
+                            const std::string& local) {
+  std::string lower_local = StringToLowerASCII(local);
+  if (lower_local.empty())
+    lower_local = kLocaleUnlocalized;
+  return key + kPathConnectSymbol + lower_local;
+}
+
+scoped_ptr<List> ExpandUserAgentLocalesList(const scoped_ptr<List>& list) {
+  scoped_ptr<List> expansion_list(new List);
+  for (List::const_iterator it = list->begin(); it != list->end(); ++it) {
+    std::string copy_locale(*it);
+    size_t position;
+    do {
+      expansion_list->push_back(copy_locale);
+      position = copy_locale.find_last_of("-");
+      copy_locale = copy_locale.substr(0, position);
+    } while (position != std::string::npos);
+  }
+  return expansion_list.Pass();
+}
+
+}  // namespace
 
 Manifest::Manifest(SourceType source_type,
         scoped_ptr<base::DictionaryValue> value)
     : source_type_(source_type),
       data_(value.Pass()),
+      i18n_data_(new base::DictionaryValue),
       type_(TYPE_UNKNOWN) {
   if (data_->HasKey(keys::kAppKey)) {
     if (data_->Get(keys::kWebURLsKey, NULL) ||
@@ -39,6 +84,15 @@ Manifest::Manifest(SourceType source_type,
     package_type_ = TYPE_WGT;
   else
     package_type_ = TYPE_XPK;
+
+  if (IsWGTPackaged())
+    ParseWGTI18n();
+
+  // Unittest may not have an xwalkrunner, so we should check here.
+  if (XWalkRunner* xwalk_runner = XWalkRunner::GetInstance())
+    SetSystemLocale(xwalk_runner->GetLocale());
+  else
+    SetSystemLocale(kLocaleUnlocalized);
 }
 
 Manifest::~Manifest() {
@@ -94,12 +148,36 @@ bool Manifest::GetInteger(
 
 bool Manifest::GetString(
     const std::string& path, std::string* out_value) const {
-  return CanAccessPath(path) && data_->GetString(path, out_value);
+  if (!CanAccessPath(path))
+    return false;
+
+  if (i18n_data_->Get(path, NULL)) {
+    List::const_iterator it = user_agent_locales_->begin();
+    for (; it != user_agent_locales_->end(); ++it) {
+      if (i18n_data_->GetString(GetLocalizedKey(path, *it), out_value))
+        return true;
+    }
+    return false;
+  }
+
+  return data_->GetString(path, out_value);
 }
 
 bool Manifest::GetString(
     const std::string& path, base::string16* out_value) const {
-  return CanAccessPath(path) && data_->GetString(path, out_value);
+  if (!CanAccessPath(path))
+    return false;
+
+  if (i18n_data_->Get(path, NULL)) {
+    List::const_iterator it = user_agent_locales_->begin();
+    for (; it != user_agent_locales_->end(); ++it) {
+      if (i18n_data_->GetString(GetLocalizedKey(path, *it), out_value))
+        return true;
+    }
+    return false;
+  }
+
+  return data_->GetString(path, out_value);
 }
 
 bool Manifest::GetDictionary(
@@ -137,5 +215,89 @@ bool Manifest::CanAccessKey(const std::string& key) const {
   return true;
 }
 
+void Manifest::SetSystemLocale(const std::string& locale) {
+  scoped_ptr<List> list_for_expand(new List);
+  list_for_expand->push_back(locale);
+  list_for_expand->push_back(default_locale_);
+  list_for_expand->push_back(kLocaleUnlocalized);
+  list_for_expand->push_back(kLocaleAuto);
+  list_for_expand->push_back(kLocaleFirstOne);
+  user_agent_locales_ = ExpandUserAgentLocalesList(list_for_expand);
+}
+
+void Manifest::ParseWGTI18n() {
+  data_->GetString(application_widget_keys::kDefaultLocaleKey,
+                   &default_locale_);
+  default_locale_ = StringToLowerASCII(default_locale_);
+
+  ParseWGTI18nEachPath(kWidgetNamePath);
+  ParseWGTI18nEachPath(kWidgetDecriptionPath);
+  ParseWGTI18nEachPath(kWidgetLicensePath);
+}
+
+// We might get one element of a list of element from path,
+// and we parse each element for fast access.
+// For example config.xml is:
+// <widget>
+//   <name>unlocalized name</name>
+//   <name xml:lang="zh-CN">zh-CN name</name>
+//   <name xml:lang="en-US" short="en-US short">en-US name</name>
+// </widget>
+// The path for value in i18n_data_ are :
+// "widget.name.#text.@unlocalized" => "unlocalized name".
+// "widget.name.#text.zh-cn" => "zh-CN name".
+// "widget.name.#text.en-us" => "en-US name".
+// "widget.name.@short.en-us" => "en-US short".
+// "widget.name.#text.*" => "unlocalized name". (the first one)
+// "widget.name.@short.*" => "". (the first one do not have a short name)
+void Manifest::ParseWGTI18nEachPath(const std::string& path) {
+  base::Value* value = NULL;
+  if (!data_->Get(path, &value))
+    return;
+
+  if (value->IsType(base::Value::TYPE_DICTIONARY)) {
+    ParseWGTI18nEachElement(value, path);
+    ParseWGTI18nEachElement(value, path, kLocaleFirstOne);
+  } else if (value->IsType(base::Value::TYPE_LIST)) {
+    base::ListValue* list;
+    value->GetAsList(&list);
+
+    bool get_first_one = false;
+    for (base::ListValue::iterator it = list->begin();
+        it != list->end(); ++it) {
+      ParseWGTI18nEachElement(*it, path);
+      if (!get_first_one)
+        get_first_one = ParseWGTI18nEachElement(*it, path, kLocaleFirstOne);
+    }
+  }
+  // After Parse we remove this path from data_ for saving memory.
+  scoped_ptr<base::Value> remove_value;
+  data_->Remove(path, &remove_value);
+}
+
+bool Manifest::ParseWGTI18nEachElement(base::Value* value,
+                                       const std::string& path,
+                                       const std::string& locale) {
+  base::DictionaryValue* dict;
+  if (!value->GetAsDictionary(&dict))
+    return false;
+
+  std::string xml_lang(locale);
+  if (locale.empty())
+    dict->GetString(application_widget_keys::kXmlLangKey, &xml_lang);
+
+  base::DictionaryValue::Iterator iter(*dict);
+  while (!iter.IsAtEnd()) {
+    std::string locale_key(
+        GetLocalizedKey(path + kPathConnectSymbol + iter.key(), xml_lang));
+    if (!i18n_data_->Get(locale_key, NULL))
+      i18n_data_->Set(locale_key, iter.value().DeepCopy());
+
+    iter.Advance();
+  }
+
+  return true;
+}
+
 }  // namespace application
 }  // namespace xwalk
index ad75d8b..d484404 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef XWALK_APPLICATION_COMMON_MANIFEST_H_
 #define XWALK_APPLICATION_COMMON_MANIFEST_H_
 
+#include <list>
 #include <map>
 #include <string>
 #include <set>
@@ -72,6 +73,7 @@ class Manifest {
 
   PackageType GetPackageType() const { return package_type_; }
   bool IsXPKPackaged() const { return package_type_ == TYPE_XPK; }
+  bool IsWGTPackaged() const { return package_type_ == TYPE_WGT; }
 
   // These access the wrapped manifest value, returning false when the property
   // does not exist or if the manifest type can't access it.
@@ -81,8 +83,17 @@ class Manifest {
   bool Get(const std::string& path, base::Value** out_value) const;
   bool GetBoolean(const std::string& path, bool* out_value) const;
   bool GetInteger(const std::string& path, int* out_value) const;
+
+  // If the path is supported by i18n, we can get a locale string from
+  // this two GetString function. The following is locale priority:
+  // Application locale (locale get from system).                 | high
+  // Default locale (defaultlocale attribute of widget element)
+  // Unlocalized (the element without xml:lang attribute)
+  // Auto ("en-us"(tizen is "en-gb") will be considered as a default)
+  // First (the worst case we get the first element)              | low
   bool GetString(const std::string& path, std::string* out_value) const;
   bool GetString(const std::string& path, base::string16* out_value) const;
+
   bool GetDictionary(const std::string& path,
                      const base::DictionaryValue** out_value) const;
   bool GetList(const std::string& path,
@@ -99,7 +110,20 @@ class Manifest {
   // Note: only use this when you KNOW you don't need the validation.
   const base::DictionaryValue* value() const { return data_.get(); }
 
+  const std::string& default_locale() const {
+    return default_locale_;
+  }
+
+  // Update user agent locale when system locale is changed.
+  void SetSystemLocale(const std::string& locale);
+
  private:
+  void ParseWGTI18n();
+  void ParseWGTI18nEachPath(const std::string& path);
+  bool ParseWGTI18nEachElement(base::Value* value,
+                               const std::string& path,
+                               const std::string& locale = "");
+
   // Returns true if the application can specify the given |path|.
   bool CanAccessPath(const std::string& path) const;
   bool CanAccessKey(const std::string& key) const;
@@ -115,6 +139,10 @@ class Manifest {
 
   // The underlying dictionary representation of the manifest.
   scoped_ptr<base::DictionaryValue> data_;
+  scoped_ptr<base::DictionaryValue> i18n_data_;
+
+  std::string default_locale_;
+  scoped_ptr<std::list<std::string> > user_agent_locales_;
 
   Type type_;
 
index 810c9aa..7f9a630 100644 (file)
@@ -12,6 +12,7 @@
 #if defined(OS_TIZEN)
 #include "xwalk/application/common/manifest_handlers/navigation_handler.h"
 #include "xwalk/application/common/manifest_handlers/tizen_application_handler.h"
+#include "xwalk/application/common/manifest_handlers/tizen_metadata_handler.h"
 #include "xwalk/application/common/manifest_handlers/tizen_setting_handler.h"
 #endif
 #include "xwalk/application/common/manifest_handlers/permissions_handler.h"
@@ -79,6 +80,7 @@ ManifestHandlerRegistry::GetInstanceForWGT() {
   handlers.push_back(new NavigationHandler);
   handlers.push_back(new TizenApplicationHandler);
   handlers.push_back(new TizenSettingHandler);
+  handlers.push_back(new TizenMetaDataHandler);
 #endif
   widget_registry_ = new ManifestHandlerRegistry(handlers);
   return widget_registry_;
diff --git a/src/xwalk/application/common/manifest_handlers/tizen_metadata_handler.cc b/src/xwalk/application/common/manifest_handlers/tizen_metadata_handler.cc
new file mode 100644 (file)
index 0000000..98fd3df
--- /dev/null
@@ -0,0 +1,106 @@
+// 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/application/common/manifest_handlers/tizen_metadata_handler.h"
+
+#include <map>
+#include <utility>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "xwalk/application/common/application_manifest_constants.h"
+
+
+namespace xwalk {
+
+namespace keys = application_widget_keys;
+
+typedef std::pair<std::string, std::string> MetaDataPair;
+typedef std::map<std::string, std::string> MetaDataMap;
+typedef std::map<std::string, std::string>::const_iterator MetaDataIter;
+
+namespace {
+
+MetaDataPair ParseMetaDataItem(const base::DictionaryValue* dict,
+                               base::string16* error) {
+  DCHECK(dict && dict->IsType(base::Value::TYPE_DICTIONARY));
+  MetaDataPair result;
+  std::string value;
+  if (!dict->GetString(keys::kTizenMetaDataNameKey, &result.first) ||
+      !dict->GetString(keys::kTizenMetaDataValueKey, &result.second)) {
+    *error = base::ASCIIToUTF16("Invalid key/value of tizen metaData.");
+  }
+
+  return result;
+}
+}  // namespace
+
+namespace application {
+
+TizenMetaDataInfo::TizenMetaDataInfo() {}
+
+TizenMetaDataInfo::~TizenMetaDataInfo() {}
+
+bool TizenMetaDataInfo::HasKey(const std::string& key) const {
+  return metadata_.find(key) != metadata_.end();
+}
+
+std::string TizenMetaDataInfo::GetValue(const std::string& key) const {
+  MetaDataIter it = metadata_.find(key);
+  if (it != metadata_.end())
+    return it->second;
+  return std::string("");
+}
+
+void TizenMetaDataInfo::SetValue(const std::string& key,
+                                 const std::string& value) {
+  metadata_.insert(MetaDataPair(key, value));
+}
+
+TizenMetaDataHandler::TizenMetaDataHandler() {
+}
+
+TizenMetaDataHandler::~TizenMetaDataHandler() {}
+
+bool TizenMetaDataHandler::Parse(scoped_refptr<ApplicationData> application,
+                                 base::string16* error) {
+  scoped_ptr<TizenMetaDataInfo> metadata_info(new TizenMetaDataInfo);
+  const Manifest* manifest = application->GetManifest();
+  DCHECK(manifest);
+
+  base::Value* metadata_value = NULL;
+  if (!manifest->Get(keys::kTizenMetaDataKey, &metadata_value)) {
+    *error = base::ASCIIToUTF16("Failed to get value of tizen metaData");
+  }
+
+  MetaDataPair metadata_item;
+  if (metadata_value && metadata_value->IsType(base::Value::TYPE_DICTIONARY)) {
+    base::DictionaryValue* dict;
+    metadata_value->GetAsDictionary(&dict);
+    metadata_item = ParseMetaDataItem(dict, error);
+    metadata_info->SetValue(metadata_item.first, metadata_item.second);
+  } else if (metadata_value && metadata_value->IsType(base::Value::TYPE_LIST)) {
+    base::ListValue* list;
+    metadata_value->GetAsList(&list);
+
+    for (base::ListValue::iterator it = list->begin();
+         it != list->end(); ++it) {
+      base::DictionaryValue* dict;
+      (*it)->GetAsDictionary(&dict);
+      metadata_item = ParseMetaDataItem(dict, error);
+      metadata_info->SetValue(metadata_item.first, metadata_item.second);
+    }
+  }
+
+  application->SetManifestData(keys::kTizenMetaDataKey,
+                               metadata_info.release());
+  return true;
+}
+
+std::vector<std::string> TizenMetaDataHandler::Keys() const {
+  return std::vector<std::string>(1, keys::kTizenMetaDataKey);
+}
+
+}  // namespace application
+}  // namespace xwalk
diff --git a/src/xwalk/application/common/manifest_handlers/tizen_metadata_handler.h b/src/xwalk/application/common/manifest_handlers/tizen_metadata_handler.h
new file mode 100644 (file)
index 0000000..b0cfa9c
--- /dev/null
@@ -0,0 +1,50 @@
+// 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_APPLICATION_COMMON_MANIFEST_HANDLERS_TIZEN_METADATA_HANDLER_H_
+#define XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_TIZEN_METADATA_HANDLER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/values.h"
+#include "xwalk/application/common/application_data.h"
+#include "xwalk/application/common/manifest_handler.h"
+
+namespace xwalk {
+namespace application {
+
+class TizenMetaDataInfo : public ApplicationData::ManifestData {
+ public:
+  TizenMetaDataInfo();
+  virtual ~TizenMetaDataInfo();
+
+  bool HasKey(const std::string& key) const;
+  std::string GetValue(const std::string& key) const;
+  void SetValue(const std::string& key, const std::string& value);
+  const std::map<std::string, std::string>& metadata() const {
+    return metadata_;
+  }
+
+ private:
+  std::map<std::string, std::string> metadata_;
+};
+
+class TizenMetaDataHandler : public ManifestHandler {
+ public:
+  TizenMetaDataHandler();
+  virtual ~TizenMetaDataHandler();
+
+  virtual bool Parse(scoped_refptr<ApplicationData> application,
+                     base::string16* error) OVERRIDE;
+  virtual std::vector<std::string> Keys() const OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TizenMetaDataHandler);
+};
+
+}  // namespace application
+}  // namespace xwalk
+
+#endif  // XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_TIZEN_METADATA_HANDLER_H_
diff --git a/src/xwalk/application/common/security_policy.cc b/src/xwalk/application/common/security_policy.cc
new file mode 100644 (file)
index 0000000..f5da81f
--- /dev/null
@@ -0,0 +1,16 @@
+// 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/application/common/security_policy.h"
+
+namespace xwalk {
+namespace application {
+
+SecurityPolicy::SecurityPolicy(const GURL& url, bool subdomains)
+    : url_(url),
+      subdomains_(subdomains) {
+}
+
+}  // namespace application
+}  // namespace xwalk
diff --git a/src/xwalk/application/common/security_policy.h b/src/xwalk/application/common/security_policy.h
new file mode 100644 (file)
index 0000000..3bf5319
--- /dev/null
@@ -0,0 +1,31 @@
+// 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_APPLICATION_COMMON_SECURITY_POLICY_H_
+#define XWALK_APPLICATION_COMMON_SECURITY_POLICY_H_
+#include "url/gurl.h"
+
+namespace xwalk {
+namespace application {
+
+class SecurityPolicy {
+ public:
+  enum SecurityMode {
+    NoSecurity,
+    CSP,
+    WARP
+  };
+  SecurityPolicy(const GURL& url, bool subdomains);
+  const GURL& url() const { return url_; }
+  bool subdomains() const { return subdomains_; }
+
+ private:
+  GURL url_;
+  bool subdomains_;
+};
+
+}  // namespace application
+}  // namespace xwalk
+
+#endif  // XWALK_APPLICATION_COMMON_SECURITY_POLICY_H_
index 70895a3..21e39a4 100644 (file)
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/file_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
 #include "xwalk/application/common/application_manifest_constants.h"
@@ -70,7 +71,12 @@ AppWidgetStorage::AppWidgetStorage(Application* application,
       db_initialized_(false) {
   sqlite_db_.reset(new sql::Connection);
 
-  base::FilePath name(application_->id());
+  base::FilePath name;
+#if defined(OS_WIN)
+  name = base::FilePath(base::UTF8ToWide(application_->id()));
+#else
+  name = base::FilePath(application_->id());
+#endif
   base::FilePath::StringType storage_name =
       name.value() + kWidgetStorageExtension;
   data_path_ = data_dir.Append(storage_name);
index d3eb06e..75ffc9c 100644 (file)
@@ -10,7 +10,7 @@ XWalkExtensionProcessLauncher::XWalkExtensionProcessLauncher()
     : base::Thread("LauncherExtensionService"),
       is_started_(false) {
   base::Thread::Options thread_options;
-  thread_options.message_loop_type = base::MessageLoop::TYPE_UI;
+  thread_options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
   StartWithOptions(thread_options);
 }
 
index 8b2f5e6..2982c59 100644 (file)
@@ -95,7 +95,7 @@ static void on_app_properties_changed(GDBusProxy* proxy,
 static gboolean init_extension_process_channel(gpointer data) {
   GDBusProxy* app_proxy = static_cast<GDBusProxy*>(data);
   if (ep_launcher->is_started())
-    return TRUE;
+    return FALSE;
   // Get the client socket file descriptor from fd_list. The reply will
   // contains an index to the list.
   GUnixFDList* fd_list;
@@ -112,7 +112,7 @@ static gboolean init_extension_process_channel(gpointer data) {
   int client_fd = g_unix_fd_list_get(fd_list, client_fd_idx, NULL);
 
   ep_launcher->Launch(channel_id, client_fd);
-  return TRUE;
+  return FALSE;
 }
 
 static void on_app_signal(GDBusProxy* proxy,
index d234b85..10babd0 100644 (file)
 // be called by Crosswalk (now running as a normal user) so all the activities
 // that required 'root' access are done by a small code base.
 
-
-#if defined(OS_TIZEN)
-#include <pkgmgr/pkgmgr_parser.h>
-#else
-// So we can compile this on Linux Desktop
-static int pkgmgr_parser_parse_manifest_for_installation(
-    const char* path, char *const tagv[]) {
-  return 0;
-}
-
-static int pkgmgr_parser_parse_manifest_for_uninstallation(
-    const char* path, char *const tagv[]) {
-  return 0;
-}
-
-#endif
-
 #include "base/files/file_path.h"
 #include "base/file_util.h"
+#include "xwalk/application/tools/tizen/xwalk_pkg_installer.h"
 
 namespace {
 
-const base::FilePath kIconDir("/opt/share/icons/default/small/");
-const base::FilePath kXmlDir("/opt/share/packages/");
-const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
-const std::string kServicePrefix("xwalk-service.");
-
-class FileDeleter {
- public:
-  FileDeleter(const base::FilePath& path, bool recursive)
-      : path_(path),
-        recursive_(recursive) {}
-
-  ~FileDeleter() {
-    if (path_.empty())
-      return;
-
-    base::DeleteFile(path_, recursive_);
-  }
-
-  void Dismiss() {
-    path_.clear();
-  }
-
- private:
-  base::FilePath path_;
-  bool recursive_;
-};
-
-bool InstallApplication(const char* appid, const char* xmlpath,
-                        const char* iconpath) {
-  base::FilePath icon_src(iconpath);
-  // icon_dst == /opt/share/icons/default/small/xwalk-service.<appid>.png
-  // FIXME(vcgomes): Add support for more icon types
-  base::FilePath icon_dst = kIconDir.Append(
-      kServicePrefix + std::string(appid) + ".png");
-  if (!base::CopyFile(icon_src, icon_dst)) {
-    fprintf(stdout, "Couldn't copy application icon to '%s'\n",
-            icon_dst.value().c_str());
-    return false;
-  }
-
-  FileDeleter icon_cleaner(icon_dst, false);
-
-  base::FilePath xml_src(xmlpath);
-  base::FilePath xml_dst = kXmlDir.Append(
-      kServicePrefix + std::string(appid) + ".xml");
-  if (!base::CopyFile(xml_src, xml_dst)) {
-    fprintf(stdout, "Couldn't copy application XML metadata to '%s'\n",
-            xml_dst.value().c_str());
-    return false;
-  }
-
-  FileDeleter xml_cleaner(xml_dst, false);
-
-  if (pkgmgr_parser_parse_manifest_for_installation(xmlpath, NULL)) {
-    fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath);
-    return false;
-  }
-
-  icon_cleaner.Dismiss();
-  xml_cleaner.Dismiss();
-
-  return true;
-}
-
-bool UninstallApplication(const char* appid) {
-  bool result = true;
-
-  // FIXME(vcgomes): Add support for more icon types
-  base::FilePath icon_dst = kIconDir.Append(
-      kServicePrefix + std::string(appid) + ".png");
-  if (!base::DeleteFile(icon_dst, false)) {
-    fprintf(stdout, "Couldn't delete '%s'\n", icon_dst.value().c_str());
-    result = false;
-  }
-
-  base::FilePath xmlpath(kXmlDir);
-  xmlpath = xmlpath.Append(kServicePrefix + std::string(appid) + ".xml");
-
-  int ret = pkgmgr_parser_parse_manifest_for_uninstallation(
-      xmlpath.value().c_str(), NULL);
-  if (ret) {
-    fprintf(stdout, "Couldn't parse manifest XML '%s'\n",
-            xmlpath.value().c_str());
-    result = false;
-  }
-
-  if (!base::DeleteFile(xmlpath, false)) {
-    fprintf(stdout, "Couldn't delete '%s'\n", xmlpath.value().c_str());
-    result = false;
-  }
-
-  return result;
-}
-
 int usage(const char* program) {
   fprintf(stdout, "%s - Crosswalk Tizen Application Installation helper\n\n",
           basename(program));
@@ -150,16 +40,17 @@ int main(int argc, char *argv[]) {
     return 1;;
   }
 
+  PkgInstaller installer(argv[2]);
   if (!strcmp(argv[1], "--install")) {
     if (argc != 5)
       return usage(argv[0]);
 
-    result = InstallApplication(argv[2], argv[3], argv[4]);
+    result = installer.InstallApplication(argv[3], argv[4]);
   } else if (!strcmp(argv[1], "--uninstall")) {
     if (argc != 3)
       return usage(argv[0]);
 
-    result = UninstallApplication(argv[2]);
+    result = installer.UninstallApplication();
   } else {
     return usage(argv[0]);
   }
diff --git a/src/xwalk/application/tools/tizen/xwalk_pkg_installer.cc b/src/xwalk/application/tools/tizen/xwalk_pkg_installer.cc
new file mode 100644 (file)
index 0000000..f1144aa
--- /dev/null
@@ -0,0 +1,222 @@
+// 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/application/tools/tizen/xwalk_pkg_installer.h"
+
+#include <assert.h>
+#include <stdio.h>
+#if defined(OS_TIZEN)
+#include <pkgmgr/pkgmgr_parser.h>
+#endif
+
+#undef LOG
+#include <string>
+#include "base/files/file_path.h"
+#include "base/file_util.h"
+
+namespace {
+
+typedef int (*PkgParser)(const char*, char* const*);
+
+const base::FilePath kIconDir("/opt/share/icons/default/small/");
+const base::FilePath kXmlDir("/opt/share/packages/");
+const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
+const std::string kServicePrefix("xwalk-service.");
+
+// Package type sent in every signal.
+const char PKGMGR_PKG_TYPE[] = "rpm";
+
+// Notification about operation start.
+const char PKGMGR_START_KEY[] = "start";
+
+// Value for new installation.
+const char PKGMGR_START_INSTALL[] = "install";
+
+// Value for uninstallation.
+const char PKGMGR_START_UNINSTALL[] = "uninstall";
+
+// Notification about end of installation with status.
+const char PKGMGR_END_KEY[] = "end";
+
+// Success value of end of installation.
+const char PKGMGR_END_SUCCESS[] = "ok";
+
+// Failure value of end of installation.
+const char PKGMGR_END_FAILURE[] = "fail";
+
+const std::string kAppIdPrefix("xwalk.");
+
+class FileDeleter {
+ public:
+  FileDeleter(const base::FilePath& path, bool recursive)
+      : path_(path),
+        recursive_(recursive) {}
+
+  ~FileDeleter() {
+    if (path_.empty())
+      return;
+
+    base::DeleteFile(path_, recursive_);
+  }
+
+  void Dismiss() {
+    path_.clear();
+  }
+
+ private:
+  base::FilePath path_;
+  bool recursive_;
+};
+
+}  // namespace
+
+PkgInstaller::PkgInstaller(const std::string& appid)
+    : appid_(appid) {
+  if (appid_.empty())
+    fprintf(stdout, "Invalid app id is provided for pkg installer.\n");
+
+#if defined(OS_TIZEN)
+  handle_ = pkgmgr_installer_new();
+  if (!handle_)
+    fprintf(stdout, "Fail to get package manager installer handle.\n");
+#endif
+}
+
+PkgInstaller::~PkgInstaller() {
+#if defined(OS_TIZEN)
+  if (handle_)
+    pkgmgr_installer_free(handle_);
+#endif
+}
+
+bool PkgInstaller::InstallApplication(const std::string& xmlpath,
+                                      const std::string& iconpath) {
+  if (xmlpath.empty() || iconpath.empty()) {
+    fprintf(stdout, "Invalid xml path or icon path for installation\n");
+  }
+
+  base::FilePath icon_src(iconpath);
+  // icon_dst == /opt/share/icons/default/small/xwalk-service.<appid>.png
+  // FIXME(vcgomes): Add support for more icon types
+  base::FilePath icon_dst = kIconDir.Append(
+      kServicePrefix + std::string(appid_) + ".png");
+  if (!base::CopyFile(icon_src, icon_dst)) {
+    fprintf(stdout, "Couldn't copy application icon to '%s'\n",
+            icon_dst.value().c_str());
+    return false;
+  }
+
+  FileDeleter icon_cleaner(icon_dst, false);
+
+  base::FilePath xml_src(xmlpath);
+  base::FilePath xml_dst = kXmlDir.Append(
+      kServicePrefix + std::string(appid_) + ".xml");
+  if (!base::CopyFile(xml_src, xml_dst)) {
+    fprintf(stdout, "Couldn't copy application XML metadata to '%s'\n",
+            xml_dst.value().c_str());
+    return false;
+  }
+
+#if defined(OS_TIZEN)
+  if (!ParseManifest(PkgInstaller::INSTALL, xmlpath)) {
+    fprintf(stdout, "Couldn't install %s'\n", appid_.c_str());
+    return false;
+  }
+#endif
+
+  FileDeleter xml_cleaner(xml_dst, false);
+  icon_cleaner.Dismiss();
+  xml_cleaner.Dismiss();
+
+  return true;
+}
+
+bool PkgInstaller::UninstallApplication() {
+  bool result = true;
+
+  // FIXME(vcgomes): Add support for more icon types
+  base::FilePath icon_dst = kIconDir.Append(
+      kServicePrefix + appid_ + ".png");
+  if (!base::DeleteFile(icon_dst, false)) {
+    fprintf(stdout, "Couldn't delete '%s'\n", icon_dst.value().c_str());
+    result = false;
+  }
+
+  base::FilePath xmlpath(kXmlDir);
+  xmlpath = xmlpath.Append(kServicePrefix + std::string(appid_) + ".xml");
+
+#if defined(OS_TIZEN)
+  if (!ParseManifest(PkgInstaller::UNINSTALL, xmlpath.MaybeAsASCII())) {
+    fprintf(stdout, "Couldn't uninstall %s'\n", appid_.c_str());
+    result = false;
+  }
+#endif
+
+  if (!base::DeleteFile(xmlpath, false)) {
+    fprintf(stdout, "Couldn't delete '%s'\n", xmlpath.value().c_str());
+    result = false;
+  }
+
+  return result;
+}
+
+#if defined(OS_TIZEN)
+bool PkgInstaller::ParseManifest(PkgInstaller::RequestType type,
+                                 const std::string& xmlpath) {
+  std::string pkgmgr_cmd;
+  PkgParser parser;
+  switch (type) {
+    case PkgInstaller::INSTALL:
+      pkgmgr_cmd = PKGMGR_START_INSTALL;
+      parser = pkgmgr_parser_parse_manifest_for_installation;
+      break;
+
+    case PkgInstaller::UNINSTALL:
+      pkgmgr_cmd = PKGMGR_START_UNINSTALL;
+      parser = pkgmgr_parser_parse_manifest_for_uninstallation;
+      break;
+
+    default:
+      assert(false);
+      fprintf(stdout, "Setting unknown command for package manager.");
+      return false;
+  }
+
+  SendSignal(PKGMGR_START_KEY, pkgmgr_cmd);
+
+  bool result = parser(xmlpath.c_str(), NULL);
+
+  if (result) {
+    fprintf(stdout, "Couldn't parse manifest XML '%s'\n", xmlpath.c_str());
+    SendSignal(PKGMGR_END_KEY, PKGMGR_END_FAILURE);
+    return false;
+  } else {
+    SendSignal(PKGMGR_END_KEY, PKGMGR_END_SUCCESS);
+  }
+
+  return true;
+}
+
+bool PkgInstaller::SendSignal(
+    const std::string& key,
+    const std::string& value) {
+  if (!handle_) {
+    fprintf(stdout, "The package install manager is not initialized.\n");
+    return false;
+  }
+
+  if (key.empty() || value.empty()) {
+    fprintf(stdout, " Fail to send signal, key/value is empty.\n");
+    return false;
+  }
+
+  if (pkgmgr_installer_send_signal(
+          handle_, PKGMGR_PKG_TYPE, appid_.c_str(),
+          key.c_str(), value.c_str())) {
+    fprintf(stdout, "Fail to send package manager signal.\n");
+  }
+
+  return true;
+}
+#endif
diff --git a/src/xwalk/application/tools/tizen/xwalk_pkg_installer.h b/src/xwalk/application/tools/tizen/xwalk_pkg_installer.h
new file mode 100644 (file)
index 0000000..3e59eea
--- /dev/null
@@ -0,0 +1,37 @@
+// 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_APPLICATION_TOOLS_TIZEN_XWALK_PKG_INSTALLER_H_
+#define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PKG_INSTALLER_H_
+
+#if defined(OS_TIZEN)
+#include <pkgmgr_installer.h>
+#endif
+
+#include <string>
+
+class PkgInstaller {
+ public:
+  explicit PkgInstaller(const std::string& appid);
+  ~PkgInstaller();
+  bool InstallApplication(const std::string& xmlpath,
+                          const std::string& iconpath);
+  bool UninstallApplication();
+
+ private:
+#if defined(OS_TIZEN)
+  enum RequestType {
+    INSTALL,
+    UNINSTALL
+  };
+  bool ParseManifest(RequestType type, const std::string& xmlpath);
+  bool SendSignal(const std::string& key, const std::string& value);
+
+  pkgmgr_installer* handle_;
+#endif
+
+  std::string appid_;
+};
+
+#endif  // XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PKG_INSTALLER_H_
index 4ca57d1..7d5f60d 100644 (file)
@@ -22,6 +22,8 @@
       ],
       'sources': [
         'xwalk_pkg_helper.cc',
+        'xwalk_pkg_installer.cc',
+        'xwalk_pkg_installer.h',
       ],
     },
   ],
index 5a54603..905e4cc 100644 (file)
@@ -76,6 +76,8 @@
         'common/permission_policy_manager.cc',
         'common/permission_policy_manager.h',
         'common/permission_types.h',
+        'common/security_policy.cc',
+        'common/security_policy.h',
 
         'extension/application_event_extension.cc',
         'extension/application_event_extension.h',
             'common/manifest_handlers/navigation_handler.h',
             'common/manifest_handlers/tizen_application_handler.cc',
             'common/manifest_handlers/tizen_application_handler.h',
+            'common/manifest_handlers/tizen_metadata_handler.cc',
+            'common/manifest_handlers/tizen_metadata_handler.h',
             'common/manifest_handlers/tizen_setting_handler.cc',
             'common/manifest_handlers/tizen_setting_handler.h',
           ],
index 9e55c58..97bbed7 100755 (executable)
@@ -7,13 +7,10 @@ SCRIPT_DIR="$(dirname "${BASH_SOURCE:-$0}")"
 
 . ${SCRIPT_DIR}/../../../build/android/envsetup.sh "$@"
 
-unset CHROMIUM_GYP_FILE
-
 export PATH=$PATH:${CHROME_SRC}/xwalk/build/android
 
+# The purpose of this function is to do the same as android_gyp(), but calling
+# gyp_xwalk instead.
 xwalk_android_gyp() {
-  echo "GYP_GENERATORS set to '$GYP_GENERATORS'"
-  (
-    "${CHROME_SRC}/xwalk/gyp_xwalk" --check "$@"
-  )
+  "${CHROME_SRC}/xwalk/gyp_xwalk" --check "$@"
 }
old mode 100644 (file)
new mode 100755 (executable)
index ce224cc..e501026
@@ -126,6 +126,7 @@ def PrepareFromXwalk(src_dir, target_dir):
      os.path.join(target_dir, 'scripts/ant')),
     (os.path.join(tools_src_dir, 'compress_js_and_css.py'), target_dir),
     (os.path.join(tools_src_dir, 'customize.py'), target_dir),
+    (os.path.join(tools_src_dir, 'customize_launch_screen.py'), target_dir),
     (os.path.join(tools_src_dir, 'handle_permissions.py'), target_dir),
     (os.path.join(tools_src_dir, 'handle_xml.py'), target_dir),
     (os.path.join(tools_src_dir, 'make_apk.py'), target_dir),
index 7d65e81..c64965a 100755 (executable)
@@ -61,102 +61,6 @@ def CopyProjectFiles(project_source, out_dir):
     shutil.copy2(source_file, target_file)
 
 
-def CopyJavaSources(project_source, out_dir):
-  """cp <path>/java/src/<package>
-        out/Release/xwalk_core_library/src/<package>
-  """
-
-  print 'Copying Java sources...'
-  target_source_dir = os.path.join(
-      out_dir, LIBRARY_PROJECT_NAME, 'src')
-  if not os.path.exists(target_source_dir):
-    os.makedirs(target_source_dir)
-
-  # FIXME(wang16): There is an assumption here the package names listed
-  # here are all beginned with "org". If the assumption is broken in
-  # future, the logic needs to be adjusted accordingly.
-  java_srcs_to_copy = [
-      # Chromium java sources.
-      'base/android/java/src/org/chromium/base',
-      'content/public/android/java/src/org/chromium/content',
-      'content/public/android/java/src/org/chromium/content_public',
-      'media/base/android/java/src/org/chromium/media',
-      'net/android/java/src/org/chromium/net',
-      'ui/android/java/src/org/chromium/ui',
-      'components/navigation_interception/android/java/'
-          'src/org/chromium/components/navigation_interception',
-      'components/web_contents_delegate_android/android/java/'
-          'src/org/chromium/components/web_contents_delegate_android',
-
-      # R.javas
-      'content/public/android/java/resource_map/org/chromium/content/R.java',
-      'ui/android/java/resource_map/org/chromium/ui/R.java',
-
-      # XWalk java sources.
-      'xwalk/runtime/android/core/src/org/xwalk/core',
-      'xwalk/extensions/android/java/src/org/xwalk/core/extensions',
-  ]
-
-  for source in java_srcs_to_copy:
-    # find the src/org in the path
-    slash_org_pos = source.find(r'/org/')
-    if slash_org_pos < 0:
-      raise Exception('Invalid java source path: %s' % source)
-    source_path = os.path.join(project_source, source)
-    package_path = source[slash_org_pos+1:]
-    target_path = os.path.join(target_source_dir, package_path)
-    if os.path.isfile(source_path):
-      if not os.path.isdir(os.path.dirname(target_path)):
-        os.makedirs(os.path.dirname(target_path))
-      shutil.copyfile(source_path, target_path)
-    else:
-      shutil.copytree(source_path, target_path)
-
-
-def CopyGeneratedSources(out_dir):
-  """cp out/Release/gen/templates/<path>
-        out/Release/xwalk_core_library/src/<path>
-     cp out/Release/xwalk_core_shell_apk/
-            native_libraries_java/NativeLibraries.java
-        out/Release/xwalk_core_library/src/org/
-            chromium/base/library_loader/NativeLibraries.java
-  """
-
-  print 'Copying generated source files...'
-  generated_srcs_to_copy = [
-      'org/chromium/base/ApplicationState.java',
-      'org/chromium/base/MemoryPressureLevelList.java',
-      'org/chromium/base/library_loader/NativeLibraries.java',
-      'org/chromium/content/browser/GestureEventType.java',
-      'org/chromium/content/browser/input/PopupItemType.java',
-      'org/chromium/content/browser/PageTransitionTypes.java',
-      'org/chromium/content/browser/SpeechRecognitionError.java',
-      'org/chromium/content/common/ResultCodes.java',
-      'org/chromium/content/common/ScreenOrientationValues.java',
-      'org/chromium/content/common/TopControlsState.java',
-      'org/chromium/media/ImageFormat.java',
-      'org/chromium/net/CertificateMimeType.java',
-      'org/chromium/net/CertVerifyStatusAndroid.java',
-      'org/chromium/net/NetError.java',
-      'org/chromium/net/PrivateKeyType.java',
-      'org/chromium/ui/gfx/BitmapFormat.java',
-      'org/chromium/ui/WindowOpenDisposition.java'
-  ]
-
-  for source in generated_srcs_to_copy:
-    source_file = os.path.join(out_dir, 'gen', 'templates', source)
-    target_file = os.path.join(
-        out_dir, LIBRARY_PROJECT_NAME, 'src', source)
-    shutil.copyfile(source_file, target_file)
-
-  source_file = os.path.join(out_dir, XWALK_CORE_SHELL_APK,
-                             'native_libraries_java',
-                             'NativeLibraries.java')
-  target_file = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'src', 'org',
-                             'chromium', 'base', 'library_loader',
-                             'NativeLibraries.java')
-  shutil.copyfile(source_file, target_file)
-
 def CopyJSBindingFiles(project_source, out_dir):
   print 'Copying js binding files...'
   jsapi_dir = os.path.join(out_dir,
@@ -227,9 +131,7 @@ def CopyBinaries(out_dir):
     os.mkdir(libs_dir)
 
   libs_to_copy = [
-      'eyesfree_java.jar',
-      'guava_javalib.jar',
-      'jsr_305_javalib.jar',
+      'xwalk_core_library_java.jar',
   ]
 
   for lib in libs_to_copy:
@@ -328,9 +230,6 @@ def main(argv):
 
   # Copy Eclipse project files of library project.
   CopyProjectFiles(options.source, out_dir)
-  # Copy Java sources of chromium and xwalk.
-  CopyJavaSources(options.source, out_dir)
-  CopyGeneratedSources(out_dir)
   # Copy binaries and resuorces.
   CopyResources(options.source, out_dir)
   CopyBinaries(out_dir)
@@ -342,6 +241,10 @@ def main(argv):
   mode = os.path.basename(os.path.normpath(out_dir))
   RemoveUnusedFilesInReleaseMode(mode,
       os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs'))
+  # Create empty src directory
+  src_dir = os.path.join(out_project_dir, 'src')
+  if not os.path.isdir(src_dir):
+    os.mkdir(src_dir)
   print 'Your Android library project has been created at %s' % (
       out_project_dir)
 
diff --git a/src/xwalk/build/android/merge_jars.py b/src/xwalk/build/android/merge_jars.py
new file mode 100755 (executable)
index 0000000..5947769
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+# Copyright 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.
+
+import fnmatch
+import optparse
+import os
+import sys
+import shutil
+import subprocess
+
+
+def GetCommandOutput(command, cwd=None):
+  proc = subprocess.Popen(command, stdout=subprocess.PIPE,
+                          stderr=subprocess.STDOUT, bufsize=1,
+                          cwd=cwd)
+  output = proc.communicate()[0]
+  result = proc.returncode
+  if result:
+    raise Exception('%s: %s' % (subprocess.list2cmdline(command), output))
+  return output
+
+
+def UnpackJar(jar, classes_dir):
+  jar_cmd = ['jar', 'xvf', os.path.abspath(jar)]
+  GetCommandOutput(jar_cmd, classes_dir)
+
+
+def FindInDirectory(directory, filename_filter):
+  files = []
+  for root, _dirnames, filenames in os.walk(directory):
+    matched_files = fnmatch.filter(filenames, filename_filter)
+    files.extend((os.path.join(root, f) for f in matched_files))
+  return files
+
+
+def DoJar(classes_dir, jar_path):
+  class_files = FindInDirectory(classes_dir, '*.class')
+
+  jar_path = os.path.abspath(jar_path)
+
+  class_files_rel = [os.path.relpath(f, classes_dir) for f in class_files]
+  jar_cmd = ['jar', 'cf0', jar_path] + class_files_rel
+
+  GetCommandOutput(jar_cmd, classes_dir)
+
+
+def main():
+  parser = optparse.OptionParser()
+  info = ('The folder to place unzipped classes')
+  parser.add_option('--classes-dir', help=info)
+  info = ('The jars to merge')
+  parser.add_option('--jars', help=info)
+  info = ('The output merged jar file')
+  parser.add_option('--jar-path', help=info)
+  options, _ = parser.parse_args()
+
+  if os.path.isdir(options.classes_dir):
+    shutil.rmtree(options.classes_dir)
+  os.makedirs(options.classes_dir)
+
+  for jar in options.jars.split(' '):
+    UnpackJar(eval(jar), options.classes_dir)
+
+  DoJar(options.classes_dir, options.jar_path)
+
+if __name__ == '__main__':
+  sys.exit(main())
index 2dc267b..6bf7a55 100644 (file)
@@ -12,6 +12,7 @@
           'variables': {
             'packages': [
               'capi-location-manager',
+              'vconf',
             ],
           },
           'direct_dependent_settings': {
           'type': 'none',
           'variables': {
             'packages': [
+              'dlog',
               'pkgmgr-parser',
               'pkgmgr-info',
+              'pkgmgr-installer',
             ],
           },
           'direct_dependent_settings': {
index e97b759..ea52ff1 100644 (file)
@@ -18,7 +18,7 @@ import org.chromium.base.JNINamespace;
 @JNINamespace("xwalk::extensions")
 public abstract class XWalkExtensionAndroid {
     private final static String TAG = "XWalkExtensionAndroid";
-    private int mXWalkExtension;
+    private long mXWalkExtension;
 
     public XWalkExtensionAndroid(String name, String jsApi) {
         mXWalkExtension = nativeGetOrCreateExtension(name, jsApi, null);
@@ -62,8 +62,8 @@ public abstract class XWalkExtensionAndroid {
     @CalledByNative
     public abstract String handleSyncMessage(int instanceID, String message);
 
-    private native int nativeGetOrCreateExtension(String name, String jsApi, String[] entryPoints);
-    private native void nativePostMessage(int nativeXWalkExtensionAndroid, int instanceID, String message);
-    private native void nativeBroadcastMessage(int nativeXWalkExtensionAndroid, String message);
-    private native void nativeDestroyExtension(int nativeXWalkExtensionAndroid);
+    private native long nativeGetOrCreateExtension(String name, String jsApi, String[] entryPoints);
+    private native void nativePostMessage(long nativeXWalkExtensionAndroid, int instanceID, String message);
+    private native void nativeBroadcastMessage(long nativeXWalkExtensionAndroid, String message);
+    private native void nativeDestroyExtension(long nativeXWalkExtensionAndroid);
 }
index 93af2ce..fcbc711 100644 (file)
@@ -79,13 +79,14 @@ class ExtensionSandboxedProcessLauncherDelegate
   explicit ExtensionSandboxedProcessLauncherDelegate(
       content::ChildProcessHost* host)
 #if defined(OS_POSIX)
-      : ipc_fd_(host->TakeClientFileDescriptor()) {}
+      : ipc_fd_(host->TakeClientFileDescriptor())
 #endif
+  {}
   virtual ~ExtensionSandboxedProcessLauncherDelegate() {}
 
 #if defined(OS_WIN)
-  virtual void ShouldSandbox(bool* in_sandbox) OVERRIDE {
-    *in_sandbox = false;
+  virtual bool ShouldSandbox() OVERRIDE {
+    return false;
   }
 #elif defined(OS_POSIX)
   virtual int GetIpcFd() OVERRIDE {
@@ -216,7 +217,7 @@ void XWalkExtensionProcessHost::StartProcess() {
 }
 
 void XWalkExtensionProcessHost::StopProcess() {
-  if (process_);
+  if (process_)
     process_.reset();
   if (channel_)
     channel_.reset();
index 38d515c..db9c7a9 100644 (file)
@@ -197,7 +197,7 @@ void XWalkExtensionAndroidInstance::HandleSyncMessage(
   SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
 }
 
-static jint GetOrCreateExtension(JNIEnv* env, jobject obj, jstring name,
+static jlong GetOrCreateExtension(JNIEnv* env, jobject obj, jstring name,
                                  jstring js_api, jobjectArray js_entry_points) {
   xwalk::XWalkBrowserMainPartsAndroid* main_parts =
       ToAndroidMainParts(XWalkContentBrowserClient::Get()->main_parts());
@@ -215,7 +215,7 @@ static jint GetOrCreateExtension(JNIEnv* env, jobject obj, jstring name,
     static_cast<XWalkExtensionAndroid*>(extension)->BindToJavaObject(env, obj);
   }
 
-  return reinterpret_cast<jint>(extension);
+  return reinterpret_cast<intptr_t>(extension);
 }
 
 bool RegisterXWalkExtensionAndroid(JNIEnv* env) {
index f3cad41..292de2f 100644 (file)
@@ -2,7 +2,7 @@
 %bcond_with wayland
 
 Name:           crosswalk
-Version:        6.35.121.0
+Version:        6.35.131.0
 Release:        0
 Summary:        Crosswalk is an app runtime based on Chromium
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -50,6 +50,7 @@ BuildRequires:  pkgconfig(libxml-2.0)
 BuildRequires:  pkgconfig(libxslt)
 BuildRequires:  pkgconfig(pango)
 BuildRequires:  pkgconfig(pkgmgr-info)
+BuildRequires:  pkgconfig(pkgmgr-installer)
 BuildRequires:  pkgconfig(pkgmgr-parser)
 BuildRequires:  pkgconfig(nspr)
 BuildRequires:  pkgconfig(nss)
@@ -141,7 +142,7 @@ if [ -n "${BUILDDIR_NAME}" ]; then
 fi
 
 %if %{with wayland}
-GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1 -Denable_xdg_shell=1"
 %endif
 
 # --no-parallel is added because chroot does not mount a /dev/shm, this will
index 698e394..1373072 100644 (file)
@@ -99,6 +99,26 @@ class AndroidProtocolHandler {
         }
     }
 
+    static String getUrlContent(Context context, String url) throws IOException {
+        InputStream stream = open(context, url);
+        if (stream == null) {
+            throw new RuntimeException("Failed to open the url: " + url);
+        }
+
+        String content = "";
+        try {
+            final int bufferSize = 1024;
+            byte[] buffer = new byte[bufferSize];
+            int actualSize = 0;
+            while ((actualSize = stream.read(buffer, 0, bufferSize)) > 0) {
+                content += new String(buffer, 0, actualSize);
+            }
+        } finally {
+            stream.close();
+        }
+        return content;
+    }
+
     private static int getFieldId(Context context, String assetType, String assetName)
         throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
         Class<?> d = context.getClassLoader()
diff --git a/src/xwalk/runtime/android/core/src/org/xwalk/core/ErrorCodeConversionHelper.java b/src/xwalk/runtime/android/core/src/org/xwalk/core/ErrorCodeConversionHelper.java
new file mode 100644 (file)
index 0000000..ea2d849
--- /dev/null
@@ -0,0 +1,110 @@
+// 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;
+
+import org.chromium.net.NetError;
+
+/**
+ * This is a helper class to map native error code about loading a page to Android specific ones.
+ */
+class ErrorCodeConversionHelper {
+    static int convertErrorCode(int netError) {
+        // Note: many NetError.Error constants don't have an obvious mapping.
+        // These will be handled by the default case, ERROR_UNKNOWN.
+        switch (netError) {
+            case NetError.ERR_UNSUPPORTED_AUTH_SCHEME:
+                return XWalkResourceClient.ERROR_UNSUPPORTED_AUTH_SCHEME;
+
+            case NetError.ERR_INVALID_AUTH_CREDENTIALS:
+            case NetError.ERR_MISSING_AUTH_CREDENTIALS:
+            case NetError.ERR_MISCONFIGURED_AUTH_ENVIRONMENT:
+                return XWalkResourceClient.ERROR_AUTHENTICATION;
+
+            case NetError.ERR_TOO_MANY_REDIRECTS:
+                return XWalkResourceClient.ERROR_REDIRECT_LOOP;
+
+            case NetError.ERR_UPLOAD_FILE_CHANGED:
+                return XWalkResourceClient.ERROR_FILE_NOT_FOUND;
+
+            case NetError.ERR_INVALID_URL:
+                return XWalkResourceClient.ERROR_BAD_URL;
+
+            case NetError.ERR_DISALLOWED_URL_SCHEME:
+            case NetError.ERR_UNKNOWN_URL_SCHEME:
+                return XWalkResourceClient.ERROR_UNSUPPORTED_SCHEME;
+
+            case NetError.ERR_IO_PENDING:
+            case NetError.ERR_NETWORK_IO_SUSPENDED:
+                return XWalkResourceClient.ERROR_IO;
+
+            case NetError.ERR_CONNECTION_TIMED_OUT:
+            case NetError.ERR_TIMED_OUT:
+                return XWalkResourceClient.ERROR_TIMEOUT;
+
+            case NetError.ERR_FILE_TOO_BIG:
+                return XWalkResourceClient.ERROR_FILE;
+
+            case NetError.ERR_HOST_RESOLVER_QUEUE_TOO_LARGE:
+            case NetError.ERR_INSUFFICIENT_RESOURCES:
+            case NetError.ERR_OUT_OF_MEMORY:
+                return XWalkResourceClient.ERROR_TOO_MANY_REQUESTS;
+
+            case NetError.ERR_CONNECTION_CLOSED:
+            case NetError.ERR_CONNECTION_RESET:
+            case NetError.ERR_CONNECTION_REFUSED:
+            case NetError.ERR_CONNECTION_ABORTED:
+            case NetError.ERR_CONNECTION_FAILED:
+            case NetError.ERR_SOCKET_NOT_CONNECTED:
+                return XWalkResourceClient.ERROR_CONNECT;
+
+            case NetError.ERR_INTERNET_DISCONNECTED:
+            case NetError.ERR_ADDRESS_INVALID:
+            case NetError.ERR_ADDRESS_UNREACHABLE:
+            case NetError.ERR_NAME_NOT_RESOLVED:
+            case NetError.ERR_NAME_RESOLUTION_FAILED:
+                return XWalkResourceClient.ERROR_HOST_LOOKUP;
+
+            case NetError.ERR_SSL_PROTOCOL_ERROR:
+            case NetError.ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
+            case NetError.ERR_TUNNEL_CONNECTION_FAILED:
+            case NetError.ERR_NO_SSL_VERSIONS_ENABLED:
+            case NetError.ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
+            case NetError.ERR_SSL_RENEGOTIATION_REQUESTED:
+            case NetError.ERR_CERT_ERROR_IN_SSL_RENEGOTIATION:
+            case NetError.ERR_BAD_SSL_CLIENT_AUTH_CERT:
+            case NetError.ERR_SSL_NO_RENEGOTIATION:
+            case NetError.ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
+            case NetError.ERR_SSL_BAD_RECORD_MAC_ALERT:
+            case NetError.ERR_SSL_UNSAFE_NEGOTIATION:
+            case NetError.ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
+            case NetError.ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
+            case NetError.ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
+                return XWalkResourceClient.ERROR_FAILED_SSL_HANDSHAKE;
+
+            case NetError.ERR_PROXY_AUTH_UNSUPPORTED:
+            case NetError.ERR_PROXY_AUTH_REQUESTED:
+            case NetError.ERR_PROXY_CONNECTION_FAILED:
+            case NetError.ERR_UNEXPECTED_PROXY_AUTH:
+                return XWalkResourceClient.ERROR_PROXY_AUTHENTICATION;
+
+            // The certificate errors are handled by onReceivedSslError
+            // and don't need to be reported here.
+            case NetError.ERR_CERT_COMMON_NAME_INVALID:
+            case NetError.ERR_CERT_DATE_INVALID:
+            case NetError.ERR_CERT_AUTHORITY_INVALID:
+            case NetError.ERR_CERT_CONTAINS_ERRORS:
+            case NetError.ERR_CERT_NO_REVOCATION_MECHANISM:
+            case NetError.ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
+            case NetError.ERR_CERT_REVOKED:
+            case NetError.ERR_CERT_INVALID:
+            case NetError.ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
+            case NetError.ERR_CERT_NON_UNIQUE_NAME:
+                return XWalkResourceClient.ERROR_OK;
+
+            default:
+                return XWalkResourceClient.ERROR_UNKNOWN;
+        }
+    }
+}
diff --git a/src/xwalk/runtime/android/core/src/org/xwalk/core/JavascriptInterface.java b/src/xwalk/runtime/android/core/src/org/xwalk/core/JavascriptInterface.java
new file mode 100644 (file)
index 0000000..af18ec6
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2012 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.
+
+package org.xwalk.core;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a method as being able to be exposed to JavaScript.  This is used for
+ * safety purposes so that only explicitly marked methods get exposed instead
+ * of every method in a class.
+ * See the explanation for {@link XWalkView#addJavascriptInterface(Object, String)}
+ * about the usage.
+ */
+@SuppressWarnings("javadoc")
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface JavascriptInterface {
+}
index 4caa3e1..140f47f 100644 (file)
@@ -34,6 +34,8 @@ import android.widget.TextView;
 /**
  * It's the Internal class to handle legacy resource related callbacks not
  * handled by XWalkResourceClient.
+ *
+ * @hide
  */
 public class XWalkClient {
 
@@ -41,8 +43,8 @@ public class XWalkClient {
     private AlertDialog mDialog;
     private XWalkView mXWalkView;
 
-    public XWalkClient(Context context, XWalkView view) {
-        mContext = context;
+    public XWalkClient(XWalkView view) {
+        mContext = view.getContext();
         mXWalkView = view;
     }
 
index 3987d07..21bdf9b 100644 (file)
@@ -13,16 +13,19 @@ import android.graphics.Rect;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.ViewGroup;
 import android.webkit.ValueCallback;
 import android.webkit.WebResourceResponse;
 import android.widget.FrameLayout;
 
+import java.io.IOException;
+import java.io.InputStream;
+
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
 import org.chromium.base.ThreadUtils;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
-import org.chromium.content.browser.ContentVideoView;
 import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.ContentViewRenderView;
@@ -37,7 +40,8 @@ import org.chromium.ui.base.ActivityWindowAndroid;
  * This class is the implementation class for XWalkView by calling internal
  * various classes.
  */
-public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyValueChangeListener {
+class XWalkContent extends FrameLayout implements XWalkPreferences.KeyValueChangeListener {
+    private static String TAG = "XWalkContent";
     private ContentViewCore mContentViewCore;
     private ContentView mContentView;
     private ContentViewRenderView mContentViewRenderView;
@@ -51,10 +55,11 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
     private XWalkGeolocationPermissions mGeolocationPermissions;
     private XWalkLaunchScreenManager mLaunchScreenManager;
 
-    int mXWalkContent;
-    int mWebContents;
+    long mXWalkContent;
+    long mWebContents;
     boolean mReadyToLoad = false;
     String mPendingUrl = null;
+    String mPendingData = null;
 
     public XWalkContent(Context context, AttributeSet attrs, XWalkView xwView) {
         super(context, attrs);
@@ -73,8 +78,9 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
         mContentViewRenderView = new ContentViewRenderView(context, mWindow) {
             protected void onReadyToRender() {
                 if (mPendingUrl != null) {
-                    doLoadUrl(mPendingUrl);
+                    doLoadUrl(mPendingUrl, mPendingData);
                     mPendingUrl = null;
+                    mPendingData = null;
                 }
 
                 mReadyToLoad = true;
@@ -125,13 +131,19 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
         XWalkPreferences.load(this);
     }
 
-    void doLoadUrl(String url) {
-        //TODO(Xingnan): Configure appropriate parameters here.
+    void doLoadUrl(String url, String content) {
         // Handle the same url loading by parameters.
-        if (TextUtils.equals(url, mContentView.getUrl())) {
+        if (url != null && !url.isEmpty() &&
+                TextUtils.equals(url, mContentView.getUrl())) {
             mContentView.getContentViewCore().reload(true);
         } else {
-            LoadUrlParams params = new LoadUrlParams(url);
+            LoadUrlParams params = null;
+            if (content == null || content.isEmpty()) {
+                params = new LoadUrlParams(url);
+            } else {
+                params = LoadUrlParams.createLoadDataParamsWithBaseUrl(
+                        content, "text/html", false, url, null);
+            }
             params.setOverrideUserAgent(LoadUrlParams.UA_OVERRIDE_TRUE);
             mContentView.loadUrl(params);
         }
@@ -139,19 +151,31 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
         mContentView.requestFocus();
     }
 
-    public void loadUrl(String url) {
-        if (url == null)
+    public void loadUrl(String url, String data) {
+        if ((url == null || url.isEmpty()) &&
+                (data == null || data.isEmpty())) {
             return;
+        }
 
-        if (mReadyToLoad)
-            doLoadUrl(url);
-        else
+        if (mReadyToLoad) {
+            doLoadUrl(url, data);
+        } else {
             mPendingUrl = url;
+            mPendingData = data;
+        }
     }
 
-    public void reload() {
+    public void reload(int mode) {
         if (mReadyToLoad) {
-            mContentView.getContentViewCore().reload(true);
+            switch (mode) {
+                case XWalkView.RELOAD_IGNORE_CACHE:
+                    mContentView.getContentViewCore().reloadIgnoringCache(true);
+                    break;
+                case XWalkView.RELOAD_NORMAL:
+                default:
+                    mContentView.getContentViewCore().reload(true);
+
+            }
         }
     }
 
@@ -168,7 +192,8 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
     }
 
     public void addJavascriptInterface(Object object, String name) {
-        mContentViewCore.addJavascriptInterface(object, name);
+        mContentViewCore.addPossiblyUnsafeJavascriptInterface(object, name,
+                JavascriptInterface.class);
     }
 
     public void evaluateJavascript(String script, ValueCallback<String> callback) {
@@ -312,13 +337,36 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
         return mSettings;
     }
 
-    public void loadAppFromManifest(String path, String manifest) {
-        if (path == null || manifest == null || mXWalkContent == 0) {
+    public void loadAppFromManifest(String url, String data) {
+        if (mXWalkContent == 0 ||
+                ((url == null || url.isEmpty()) &&
+                        (data == null || data.isEmpty()))) {
             return;
         }
 
-        if (!nativeSetManifest(mXWalkContent, path, manifest)) {
-            throw new RuntimeException("Failed to parse the manifest file.");
+        String content = data;
+        // If the data of manifest.json is not set, try to load it.
+        if (data == null || data.isEmpty()) {
+            try {
+                content = AndroidProtocolHandler.getUrlContent(mXWalkView.getActivity(), url);
+            } catch (IOException e) {
+                throw new RuntimeException("Failed to read the manifest: " + url);
+            }
+        }
+
+        // Calculate the base url of manifestUrl. Used by native side.
+        // TODO(yongsheng): It's from runtime side. Need to find a better way
+        // to get base url.
+        String baseUrl = url;
+        int position = url.lastIndexOf("/");
+        if (position != -1) {
+            baseUrl = url.substring(0, position + 1);
+        } else {
+            Log.w(TAG, "The url of manifest.json is probably not set correctly.");
+        }
+
+        if (!nativeSetManifest(mXWalkContent, baseUrl, content)) {
+            throw new RuntimeException("Failed to parse the manifest file: " + url);
         }
     }
 
@@ -370,16 +418,16 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
     @CalledByNative
     public void onGetUrlFromManifest(String url) {
         if (url != null && !url.isEmpty()) {
-            loadUrl(url);
+            loadUrl(url, null);
         }
     }
 
     @CalledByNative
-    public void onGetUrlAndLaunchScreenFromManifest(String url, String readyWhen) {
+    public void onGetUrlAndLaunchScreenFromManifest(String url, String readyWhen, String imageBorder) {
         if (url == null || url.isEmpty()) return;
-        mLaunchScreenManager.displayLaunchScreen(readyWhen);
+        mLaunchScreenManager.displayLaunchScreen(readyWhen, imageBorder);
         mContentsClientBridge.registerPageLoadListener(mLaunchScreenManager);
-        loadUrl(url);
+        loadUrl(url, null);
     }
 
     @CalledByNative
@@ -433,7 +481,8 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
                 mContentsClientBridge.getCallbackHelper().postOnLoadResource(url);
             } else {
                 if (isMainFrame && webResourceResponse.getData() == null) {
-                    mContentsClientBridge.getCallbackHelper().postOnReceivedError(-1, null, url);
+                    mContentsClientBridge.getCallbackHelper().postOnReceivedError(
+                            XWalkResourceClient.ERROR_UNKNOWN, null, url);
                 }
                 interceptedRequestData = new InterceptedRequestData(webResourceResponse.getMimeType(),
                                                                     webResourceResponse.getEncoding(),
@@ -552,20 +601,26 @@ public class XWalkContent extends FrameLayout implements XWalkPreferences.KeyVal
         }
     }
 
-    private native int nativeInit(XWalkWebContentsDelegate webViewContentsDelegate,
+    public void setOverlayVideoMode(boolean enabled) {
+        if (mContentViewRenderView != null) {
+            mContentViewRenderView.setOverlayVideoMode(enabled);
+        }
+    }
+
+    private native long nativeInit(XWalkWebContentsDelegate webViewContentsDelegate,
             XWalkContentsClientBridge bridge);
-    private static native void nativeDestroy(int nativeXWalkContent);
-    private native int nativeGetWebContents(int nativeXWalkContent,
+    private static native void nativeDestroy(long nativeXWalkContent);
+    private native long nativeGetWebContents(long nativeXWalkContent,
             XWalkContentsIoThreadClient ioThreadClient,
             InterceptNavigationDelegate delegate);
-    private native void nativeClearCache(int nativeXWalkContent, boolean includeDiskFiles);
-    private native String nativeDevToolsAgentId(int nativeXWalkContent);
-    private native String nativeGetVersion(int nativeXWalkContent);
-    private native void nativeSetJsOnlineProperty(int nativeXWalkContent, boolean networkUp);
-    private native boolean nativeSetManifest(int nativeXWalkContent, String path, String manifest);
-    private native int nativeGetRoutingID(int nativeXWalkContent);
+    private native void nativeClearCache(long nativeXWalkContent, boolean includeDiskFiles);
+    private native String nativeDevToolsAgentId(long nativeXWalkContent);
+    private native String nativeGetVersion(long nativeXWalkContent);
+    private native void nativeSetJsOnlineProperty(long nativeXWalkContent, boolean networkUp);
+    private native boolean nativeSetManifest(long nativeXWalkContent, String path, String manifest);
+    private native int nativeGetRoutingID(long nativeXWalkContent);
     private native void nativeInvokeGeolocationCallback(
-            int nativeXWalkContent, boolean value, String requestingFrame);
-    private native byte[] nativeGetState(int nativeXWalkContent);
-    private native boolean nativeSetState(int nativeXWalkContent, byte[] state);
+            long nativeXWalkContent, boolean value, String requestingFrame);
+    private native byte[] nativeGetState(long nativeXWalkContent);
+    private native boolean nativeSetState(long nativeXWalkContent, byte[] state);
 }
index a2555e2..ac3f96e 100644 (file)
@@ -9,20 +9,29 @@ import android.content.Context;
 import android.view.View;
 import android.view.WindowManager;
 
+import org.chromium.base.CommandLine;
 import org.chromium.content.browser.ContentVideoViewClient;
+import org.chromium.content.common.ContentSwitches;
 import org.xwalk.core.XWalkWebChromeClient.CustomViewCallback;
 
 class XWalkContentVideoViewClient implements ContentVideoViewClient {
     private XWalkContentsClient mContentsClient;
     private Activity mActivity;
+    private XWalkView mView;
 
-    public XWalkContentVideoViewClient(XWalkContentsClient client, Activity activity) {
+    public XWalkContentVideoViewClient(XWalkContentsClient client, Activity activity, XWalkView view) {
         mContentsClient = client;
         mActivity = activity;
+        mView = view;
     }
 
     @Override
     public void onShowCustomView(View view) {
+        if (!CommandLine.getInstance().hasSwitch(
+                ContentSwitches.DISABLE_OVERLAY_FULLSCREEN_VIDEO_SUBTITLE)) {
+            mView.setOverlayVideoMode(true);
+        }
+
         CustomViewCallback cb = new CustomViewCallback() {
             @Override
             public void onCustomViewHidden() {
@@ -33,6 +42,10 @@ class XWalkContentVideoViewClient implements ContentVideoViewClient {
 
     @Override
     public void onDestroyContentVideoView() {
+        if (!CommandLine.getInstance().hasSwitch(
+                ContentSwitches.DISABLE_OVERLAY_FULLSCREEN_VIDEO_SUBTITLE)) {
+            mView.setOverlayVideoMode(false);
+        }
         mContentsClient.onHideCustomView();
     }
 
index e688753..7369611 100644 (file)
@@ -35,8 +35,7 @@ import org.chromium.net.NetError;
  * new abstract methods that the our own client must implement.
  * i.e.: all methods in this class should either be final, or abstract.
  */
-// TODO(yongsheng): remove public modifier.
-public abstract class XWalkContentsClient extends ContentViewClient {
+abstract class XWalkContentsClient extends ContentViewClient {
 
     private static final String TAG = "XWalkContentsClient";
     private final XWalkContentsClientCallbackHelper mCallbackHelper =
@@ -69,7 +68,8 @@ public abstract class XWalkContentsClient extends ContentViewClient {
                 // the XWalkView does not notify the embedder of sub-frame failures.
                 return;
             }
-            onReceivedError(errorCode, description, failingUrl);
+            onReceivedError(ErrorCodeConversionHelper.convertErrorCode(errorCode),
+                    description, failingUrl);
         }
 
         @Override
@@ -179,6 +179,9 @@ public abstract class XWalkContentsClient extends ContentViewClient {
 
     public abstract boolean hasEnteredFullscreen();
 
+    public abstract boolean shouldOverrideRunFileChooser(
+            int processId, int renderId, int mode, String acceptTypes, boolean capture);
+
     // TODO (michaelbai): Remove this method once the same method remove from
     // XWalkContentsClientAdapter.
     public void onShowCustomView(View view,
index 6693c0d..20a7860 100644 (file)
@@ -5,12 +5,16 @@
 
 package org.xwalk.core;
 
+import android.content.ContentResolver;
 import android.content.Intent;
+import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Picture;
+import android.net.Uri;
 import android.net.http.SslCertificate;
 import android.net.http.SslError;
 import android.os.Message;
+import android.provider.MediaStore;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
@@ -47,7 +51,7 @@ class XWalkContentsClientBridge extends XWalkContentsClient
     private boolean mIsFullscreen = false;
 
     // The native peer of the object
-    private int mNativeContentsClientBridge;
+    private long mNativeContentsClientBridge;
 
     private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
         private XWalkContentsClient mContentsClient;
@@ -83,7 +87,7 @@ class XWalkContentsClientBridge extends XWalkContentsClient
             mXWalkUIClient = client;
             return;
         }
-        mXWalkUIClient = new XWalkUIClientImpl(mXWalkView.getContext(), mXWalkView);
+        mXWalkUIClient = new XWalkUIClient(mXWalkView);
     }
 
     public void setResourceClient(XWalkResourceClient client) {
@@ -92,7 +96,7 @@ class XWalkContentsClientBridge extends XWalkContentsClient
             mXWalkResourceClient = client;
             return;
         }
-        mXWalkResourceClient = new XWalkResourceClientImpl(mXWalkView.getContext(), mXWalkView);
+        mXWalkResourceClient = new XWalkResourceClient(mXWalkView);
     }
 
 
@@ -133,6 +137,13 @@ class XWalkContentsClientBridge extends XWalkContentsClient
         return mInterceptNavigationDelegate;
     }
 
+    private boolean isOwnerActivityRunning() {
+        if (mXWalkView != null && mXWalkView.isOwnerActivityRunning()) {
+            return true;
+        }
+        return false;
+    }
+
     // TODO(Xingnan): All the empty functions need to be implemented.
     @Override
     public boolean shouldOverrideUrlLoading(String url) {
@@ -155,26 +166,34 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
     @Override
     public void onProgressChanged(int progress) {
-        mXWalkResourceClient.onProgressChanged(mXWalkView, progress);
+        if (isOwnerActivityRunning()) {
+            mXWalkResourceClient.onProgressChanged(mXWalkView, progress);
+        }
     }
 
     @Override
     public WebResourceResponse shouldInterceptRequest(String url) {
-        return mXWalkResourceClient.shouldInterceptLoadRequest(mXWalkView, url);
+        if (isOwnerActivityRunning()) {
+            return mXWalkResourceClient.shouldInterceptLoadRequest(mXWalkView, url);
+        }
+        return null;
     }
 
     public void onResourceLoadStarted(String url) {
-        mXWalkResourceClient.onLoadStarted(mXWalkView, url);
+        if (isOwnerActivityRunning()) {
+            mXWalkResourceClient.onLoadStarted(mXWalkView, url);
+        }
     }
 
     public void onResourceLoadFinished(String url) {
-        // TODO(yongsheng): this method is never called. Where should it be hooked?
-        mXWalkResourceClient.onLoadFinished(mXWalkView, url);
+        if (isOwnerActivityRunning()) {
+            mXWalkResourceClient.onLoadFinished(mXWalkView, url);
+        }
     }
 
     @Override
     public void onLoadResource(String url) {
-        if (mXWalkClient != null && mXWalkView != null) {
+        if (mXWalkClient != null && isOwnerActivityRunning()) {
             mXWalkClient.onLoadResource(mXWalkView, url);
         }
     }
@@ -186,14 +205,14 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
     @CalledByNative
     public void onReceivedHttpAuthRequest(XWalkHttpAuthHandler handler, String host, String realm) {
-        if (mXWalkClient != null && mXWalkView != null) {
+        if (mXWalkClient != null && isOwnerActivityRunning()) {
             mXWalkClient.onReceivedHttpAuthRequest(mXWalkView, handler, host, realm);
         }
     }
 
     @Override
     public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) {
-        if (mXWalkClient != null && mXWalkView != null) {
+        if (mXWalkClient != null && isOwnerActivityRunning()) {
             mXWalkClient.onReceivedSslError(mXWalkView, callback, error);
         }
     }
@@ -205,14 +224,14 @@ class XWalkContentsClientBridge extends XWalkContentsClient
     @Override
     public void onGeolocationPermissionsShowPrompt(String origin,
             XWalkGeolocationPermissions.Callback callback) {
-        if (mXWalkWebChromeClient != null) {
+        if (mXWalkWebChromeClient != null && isOwnerActivityRunning()) {
             mXWalkWebChromeClient.onGeolocationPermissionsShowPrompt(origin, callback);
         }
     }
 
     @Override
     public void onGeolocationPermissionsHidePrompt() {
-        if (mXWalkWebChromeClient != null) {
+        if (mXWalkWebChromeClient != null && isOwnerActivityRunning()) {
             mXWalkWebChromeClient.onGeolocationPermissionsHidePrompt();
         }
     }
@@ -228,34 +247,42 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
     @Override
     public void onPageStarted(String url) {
-        if (mXWalkClient != null && mXWalkView != null) {
+        if (mXWalkClient != null && isOwnerActivityRunning()) {
             mXWalkClient.onPageStarted(mXWalkView, url);
         }
     }
 
     @Override
     public void onPageFinished(String url) {
+        if (!isOwnerActivityRunning()) return;
         if (mPageLoadListener != null) mPageLoadListener.onPageFinished(url);
-        if (mXWalkClient != null && mXWalkView != null) {
+        if (mXWalkClient != null) {
             mXWalkClient.onPageFinished(mXWalkView, url);
         }
+
+        // This isn't the accurate point to notify a resource loading is finished,
+        // but it's a workable way. We could enhance this by extending Content
+        // API in future if we have the demand.
+        onResourceLoadFinished(url);
     }
 
     @Override
     public void onReceivedError(int errorCode, String description, String failingUrl) {
-        mXWalkResourceClient.onReceivedLoadError(mXWalkView, errorCode, description, failingUrl);
+        if (isOwnerActivityRunning()) {
+            mXWalkResourceClient.onReceivedLoadError(mXWalkView, errorCode, description, failingUrl);
+        }
     }
 
     @Override
     public void onRendererUnresponsive() {
-        if (mXWalkClient != null && mXWalkView != null) {
+        if (mXWalkClient != null && isOwnerActivityRunning()) {
             mXWalkClient.onRendererUnresponsive(mXWalkView);
         }
     }
 
     @Override
     public void onRendererResponsive() {
-        if (mXWalkClient != null && mXWalkView != null) {
+        if (mXWalkClient != null && isOwnerActivityRunning()) {
             mXWalkClient.onRendererResponsive(mXWalkView);
         }
     }
@@ -280,12 +307,16 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
     @Override
     public void onRequestFocus() {
-        mXWalkUIClient.onRequestFocus(mXWalkView);
+        if (isOwnerActivityRunning()) {
+            mXWalkUIClient.onRequestFocus(mXWalkView);
+        }
     }
 
     @Override
     public void onCloseWindow() {
-        mXWalkUIClient.onJavascriptCloseWindow(mXWalkView);
+        if (isOwnerActivityRunning()) {
+            mXWalkUIClient.onJavascriptCloseWindow(mXWalkView);
+        }
     }
 
     @Override
@@ -305,21 +336,23 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
     @Override
     public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
-        if (mXWalkWebChromeClient != null) {
+        if (mXWalkWebChromeClient != null && isOwnerActivityRunning()) {
             mXWalkWebChromeClient.onShowCustomView(view, callback);
         }
     }
 
     @Override
     public void onHideCustomView() {
-        if (mXWalkWebChromeClient != null) {
+        if (mXWalkWebChromeClient != null && isOwnerActivityRunning()) {
             mXWalkWebChromeClient.onHideCustomView();
         }
     }
 
     @Override
     public void onScaleChangedScaled(float oldScale, float newScale) {
-        mXWalkUIClient.onScaleChanged(mXWalkView, oldScale, newScale);
+        if (isOwnerActivityRunning()) {
+            mXWalkUIClient.onScaleChanged(mXWalkView, oldScale, newScale);
+        }
     }
 
     @Override
@@ -340,15 +373,17 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
     @Override
     public void onTitleChanged(String title) {
-        if (mXWalkWebChromeClient != null && mXWalkView != null) {
+        if (mXWalkWebChromeClient != null && isOwnerActivityRunning()) {
             mXWalkWebChromeClient.onReceivedTitle(mXWalkView, title);
         }
     }
 
     @Override
     public void onToggleFullscreen(boolean enterFullscreen) {
-        mIsFullscreen = enterFullscreen;
-        mXWalkUIClient.onFullscreenToggled(mXWalkView, enterFullscreen);
+        if (isOwnerActivityRunning()) {
+            mIsFullscreen = enterFullscreen;
+            mXWalkUIClient.onFullscreenToggled(mXWalkView, enterFullscreen);
+        }
     }
 
     @Override
@@ -357,13 +392,86 @@ class XWalkContentsClientBridge extends XWalkContentsClient
     }
 
     @Override
+    public boolean shouldOverrideRunFileChooser(
+            final int processId, final int renderId, final int modeFlags,
+            String acceptTypes, boolean capture) {
+        if (!isOwnerActivityRunning()) return false;
+        abstract class UriCallback implements ValueCallback<Uri> {
+            boolean syncNullReceived = false;
+            boolean syncCallFinished = false;
+            protected String resolveFileName(Uri uri, ContentResolver contentResolver) {
+                if (contentResolver == null || uri == null) return "";
+                Cursor cursor = null;
+                try {
+                    cursor = contentResolver.query(uri, null, null, null, null);
+
+                    if (cursor != null && cursor.getCount() >= 1) {
+                        cursor.moveToFirst();
+                        int index = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
+                        if (index > -1) return cursor.getString(index);
+                    }
+                } catch (NullPointerException e) {
+                    // Some android models don't handle the provider call correctly.
+                    // see crbug.com/345393
+                    return "";
+                } finally {
+                    if (cursor != null) cursor.close();
+                }
+                return "";
+            }
+        }
+        UriCallback uploadFile = new UriCallback() {
+            boolean completed = false;
+            @Override
+            public void onReceiveValue(Uri value) {
+                if (completed) {
+                    throw new IllegalStateException("Duplicate openFileChooser result");
+                }
+                completed = true;
+                if (value == null && !syncCallFinished) {
+                    syncNullReceived = true;
+                    return;
+                }
+                if (value == null) {
+                    nativeOnFilesNotSelected(mNativeContentsClientBridge,
+                            processId, renderId, modeFlags);
+                } else {
+                    String result = "";
+                    String displayName = null;
+                    if (ContentResolver.SCHEME_FILE.equals(value.getScheme())) {
+                        result = value.getSchemeSpecificPart();
+                        displayName = value.getLastPathSegment();
+                    } else if (ContentResolver.SCHEME_CONTENT.equals(value.getScheme())) {
+                        result = value.toString();
+                        displayName = resolveFileName(
+                                value, mXWalkView.getActivity().getContentResolver());
+                    } else {
+                        result = value.getPath();
+                        displayName = value.getLastPathSegment();
+                    }
+                    if (displayName == null || displayName.isEmpty()) displayName = result;
+                    nativeOnFilesSelected(mNativeContentsClientBridge,
+                            processId, renderId, modeFlags, result, displayName);
+                }
+            }
+        };
+        mXWalkUIClient.openFileChooser(
+                mXWalkView, uploadFile, acceptTypes, Boolean.toString(capture));
+        uploadFile.syncCallFinished = true;
+        // File chooser requires user interaction, valid derives should handle it in async process.
+        // If the ValueCallback receive a sync result with null value, it is considered the
+        // file chooser is not overridden.
+        return !uploadFile.syncNullReceived;
+    }
+
+    @Override
     public ContentVideoViewClient getContentVideoViewClient() {
-        return new XWalkContentVideoViewClient(this, mXWalkView.getActivity());
+        return new XWalkContentVideoViewClient(this, mXWalkView.getActivity(), mXWalkView);
     }
 
     // Used by the native peer to set/reset a weak ref to the native peer.
     @CalledByNative
-    private void setNativeContentsClientBridge(int nativeContentsClientBridge) {
+    private void setNativeContentsClientBridge(long nativeContentsClientBridge) {
         mNativeContentsClientBridge = nativeContentsClientBridge;
     }
 
@@ -399,41 +507,40 @@ class XWalkContentsClientBridge extends XWalkContentsClient
 
     @CalledByNative
     private void handleJsAlert(String url, String message, int id) {
-        XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
-        mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
-                XWalkUIClient.JavascriptMessageType.JAVASCRIPT_ALERT, url, message, "", result);
+        if (isOwnerActivityRunning()) {
+            XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
+            mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
+                    XWalkUIClient.JavascriptMessageType.JAVASCRIPT_ALERT, url, message, "", result);
+        }
     }
 
     @CalledByNative
     private void handleJsConfirm(String url, String message, int id) {
-        XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
-        mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
-                XWalkUIClient.JavascriptMessageType.JAVASCRIPT_CONFIRM, url, message, "", result);
+        if (isOwnerActivityRunning()) {
+            XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
+            mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
+                    XWalkUIClient.JavascriptMessageType.JAVASCRIPT_CONFIRM, url, message, "", result);
+        }
     }
 
     @CalledByNative
     private void handleJsPrompt(String url, String message, String defaultValue, int id) {
-        XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
-        mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
-                XWalkUIClient.JavascriptMessageType.JAVASCRIPT_PROMPT, url, message, defaultValue,
-                        result);
+        if (isOwnerActivityRunning()) {
+            XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
+            mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
+                    XWalkUIClient.JavascriptMessageType.JAVASCRIPT_PROMPT, url, message, defaultValue,
+                            result);
+        }
     }
 
     @CalledByNative
     private void handleJsBeforeUnload(String url, String message, int id) {
-        XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
-        mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
-                XWalkUIClient.JavascriptMessageType.JAVASCRIPT_BEFOREUNLOAD, url, message, "",
-                        result);
-    }
-
-    // @CalledByNative
-    // TODO(yongsheng): Native side should call file chooser.
-    public void runFileChooser(final int processId, final int renderId, final int mode_flags,
-            String acceptTypes, String title, String defaultFilename, boolean capture) {
-        // TODO(yongsheng): Implement it.
-        // mXWalkUIClient.openFileChooser(mXWalkView, ...);
-        // See https://crosswalk-project.org/jira/browse/XWALK-1241.
+        if (isOwnerActivityRunning()) {
+            XWalkJavascriptResultHandler result = new XWalkJavascriptResultHandler(this, id);
+            mXWalkUIClient.onJavascriptModalDialog(mXWalkView,
+                    XWalkUIClient.JavascriptMessageType.JAVASCRIPT_BEFOREUNLOAD, url, message, "",
+                            result);
+        }
     }
 
     @CalledByNative
@@ -465,7 +572,7 @@ class XWalkContentsClientBridge extends XWalkContentsClient
         nativeCancelJsResult(mNativeContentsClientBridge, id);
     }
 
-    void exitFullscreen(int nativeWebContents) {
+    void exitFullscreen(long nativeWebContents) {
         if (mNativeContentsClientBridge == 0) return;
         nativeExitFullscreen(mNativeContentsClientBridge, nativeWebContents);
     }
@@ -511,19 +618,23 @@ class XWalkContentsClientBridge extends XWalkContentsClient
     //--------------------------------------------------------------------------------------------
     //  Native methods
     //--------------------------------------------------------------------------------------------
-    private native void nativeProceedSslError(int nativeXWalkContentsClientBridge,
+    private native void nativeProceedSslError(long nativeXWalkContentsClientBridge,
             boolean proceed, int id);
 
-    private native void nativeConfirmJsResult(int nativeXWalkContentsClientBridge, int id,
+    private native void nativeConfirmJsResult(long nativeXWalkContentsClientBridge, int id,
             String prompt);
-    private native void nativeCancelJsResult(int nativeXWalkContentsClientBridge, int id);
-    private native void nativeExitFullscreen(int nativeXWalkContentsClientBridge, int nativeWebContents);
-    private native void nativeNotificationDisplayed(int nativeXWalkContentsClientBridge, int id,
+    private native void nativeCancelJsResult(long nativeXWalkContentsClientBridge, int id);
+    private native void nativeExitFullscreen(long nativeXWalkContentsClientBridge, long nativeWebContents);
+    private native void nativeNotificationDisplayed(long nativeXWalkContentsClientBridge, int id,
             int processId, int routeId);
-    private native void nativeNotificationError(int nativeXWalkContentsClientBridge, int id,
+    private native void nativeNotificationError(long nativeXWalkContentsClientBridge, int id,
             String error, int processId, int routeId);
-    private native void nativeNotificationClicked(int nativeXWalkContentsClientBridge, int id,
+    private native void nativeNotificationClicked(long nativeXWalkContentsClientBridge, int id,
             int processId, int routeId);
-    private native void nativeNotificationClosed(int nativeXWalkContentsClientBridge, int id,
+    private native void nativeNotificationClosed(long nativeXWalkContentsClientBridge, int id,
             boolean byUser, int processId, int routeId);
+    private native void nativeOnFilesSelected(long nativeXWalkContentsClientBridge,
+            int processId, int renderId, int mode_flags, String filepath, String displayName);
+    private native void nativeOnFilesNotSelected(long nativeXWalkContentsClientBridge,
+            int processId, int renderId, int mode_flags);
 }
index 741095f..6206cf0 100644 (file)
@@ -10,9 +10,10 @@ import org.chromium.base.JNINamespace;
  * XWalkCookieManager manages cookies according to RFC2109 spec.
  *
  * Methods in this class are thread safe.
+ *
+ * @hide
  */
 @JNINamespace("xwalk")
-// TODO(yongsheng): remove public modifier.
 public final class XWalkCookieManager {
     /**
      * Control whether cookie is enabled or disabled
index 795f1b1..b8ae00e 100644 (file)
@@ -12,7 +12,7 @@ import org.chromium.base.JNINamespace;
 @JNINamespace("xwalk")
 class XWalkDevToolsServer {
 
-    private int mNativeDevToolsServer = 0;
+    private long mNativeDevToolsServer = 0;
 
     public XWalkDevToolsServer(String socketName) {
         mNativeDevToolsServer = nativeInitRemoteDebugging(socketName);
@@ -35,9 +35,9 @@ class XWalkDevToolsServer {
         nativeAllowConnectionFromUid(mNativeDevToolsServer, uid);
     }
 
-    private native int nativeInitRemoteDebugging(String socketName);
-    private native void nativeDestroyRemoteDebugging(int devToolsServer);
-    private native boolean nativeIsRemoteDebuggingEnabled(int devToolsServer);
-    private native void nativeSetRemoteDebuggingEnabled(int devToolsServer, boolean enabled);
-    private native void nativeAllowConnectionFromUid(int devToolsServer, int uid);
+    private native long nativeInitRemoteDebugging(String socketName);
+    private native void nativeDestroyRemoteDebugging(long devToolsServer);
+    private native boolean nativeIsRemoteDebuggingEnabled(long devToolsServer);
+    private native void nativeSetRemoteDebuggingEnabled(long devToolsServer, boolean enabled);
+    private native void nativeAllowConnectionFromUid(long devToolsServer, int uid);
 }
index 6bba779..e384ba2 100644 (file)
@@ -17,7 +17,7 @@ import org.chromium.net.GURLUtils;
  * This class is used to manage permissions for the WebView's Geolocation JavaScript API.
  *
  * Callbacks are posted on the UI thread.
- * TODO(yongsheng): remove public modifier.
+ * @hide
  */
 public final class XWalkGeolocationPermissions {
     /**
index 728ac34..db6078d 100644 (file)
@@ -7,11 +7,14 @@ package org.xwalk.core;
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
 
+/**
+ * It's for http auth handling.
+ * @hide
+ */
 @JNINamespace("xwalk")
-// TODO(yongsheng): remove public modifier.
 public class XWalkHttpAuthHandler {
 
-    private int mNativeXWalkHttpAuthHandler;
+    private long mNativeXWalkHttpAuthHandler;
     private final boolean mFirstAttempt;
 
     public void proceed(String username, String password) {
@@ -33,11 +36,11 @@ public class XWalkHttpAuthHandler {
     }
 
     @CalledByNative
-    public static XWalkHttpAuthHandler create(int nativeXWalkAuthHandler, boolean firstAttempt) {
+    public static XWalkHttpAuthHandler create(long nativeXWalkAuthHandler, boolean firstAttempt) {
         return new XWalkHttpAuthHandler(nativeXWalkAuthHandler, firstAttempt);
     }
 
-    private XWalkHttpAuthHandler(int nativeXWalkHttpAuthHandler, boolean firstAttempt) {
+    private XWalkHttpAuthHandler(long nativeXWalkHttpAuthHandler, boolean firstAttempt) {
         mNativeXWalkHttpAuthHandler = nativeXWalkHttpAuthHandler;
         mFirstAttempt = firstAttempt;
     }
@@ -47,8 +50,8 @@ public class XWalkHttpAuthHandler {
         mNativeXWalkHttpAuthHandler = 0;
     }
 
-    private native void nativeProceed(int nativeXWalkHttpAuthHandler,
+    private native void nativeProceed(long nativeXWalkHttpAuthHandler,
             String username, String password);
-    private native void nativeCancel(int nativeXWalkHttpAuthHandler);
+    private native void nativeCancel(long nativeXWalkHttpAuthHandler);
 }
 
index 5265901..bb0d099 100644 (file)
@@ -5,6 +5,7 @@
 package org.xwalk.core;
 
 import java.lang.Runnable;
+import java.util.ArrayList;
 
 import android.app.Activity;
 import android.app.Dialog;
@@ -13,32 +14,50 @@ import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.Shader.TileMode;
+import android.hardware.SensorManager;
 import android.os.Bundle;
+import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.TypedValue;
+import android.view.Display;
 import android.view.Gravity;
 import android.view.KeyEvent;
+import android.view.OrientationEventListener;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
 
 import org.chromium.content.browser.ContentViewRenderView.FirstRenderedFrameListener;
 
-// Provisionally set it as public due to the use of launch screen extension.
-// TODO(yongsheng): remove public modifier.
+/**
+ * Provisionally set it as public due to the use of launch screen extension.
+ * @hide
+ */
 public class XWalkLaunchScreenManager
-        implements FirstRenderedFrameListener, DialogInterface.OnShowListener, PageLoadListener {
+        implements FirstRenderedFrameListener, DialogInterface.OnShowListener,
+                  DialogInterface.OnDismissListener, PageLoadListener {
     // This string will be initialized before extension initialized,
     // and used by LaunchScreenExtension.
     private static String mIntentFilterStr;
 
+    private final static String BORDER_MODE_REPEAT = "repeat";
+    private final static String BORDER_MODE_STRETCH = "stretch";
+    private final static String BORDER_MODE_ROUND = "round";
+
     private XWalkView mXWalkView;
     private Activity mActivity;
     private Context mLibContext;
@@ -48,6 +67,8 @@ public class XWalkLaunchScreenManager
     private boolean mFirstFrameReceived;
     private BroadcastReceiver mLaunchScreenReadyWhenReceiver;
     private boolean mCustomHideLaunchScreen;
+    private int mCurrentOrientation;
+    private OrientationEventListener mOrientationListener;
 
     private enum ReadyWhenType {
         FIRST_PAINT,
@@ -56,6 +77,13 @@ public class XWalkLaunchScreenManager
         CUSTOM
     }
 
+    private enum BorderModeType {
+        REPEAT,
+        STRETCH,
+        ROUND,
+        NONE
+    }
+
     public XWalkLaunchScreenManager(Context context, XWalkView xwView) {
         mXWalkView = xwView;
         mLibContext = context;
@@ -63,39 +91,63 @@ public class XWalkLaunchScreenManager
         mIntentFilterStr = mActivity.getPackageName() + ".hideLaunchScreen";
     }
 
-    public void displayLaunchScreen(String readyWhen) {
+    public void displayLaunchScreen(String readyWhen, final String imageBorderList) {
         if (mXWalkView == null) return;
         setReadyWhen(readyWhen);
 
         Runnable runnable = new Runnable() {
-           public void run(){
-                int resId = mActivity.getResources().getIdentifier(
-                        "launchscreen", "drawable", mActivity.getPackageName());
-                if (resId == 0) return;
-
-                // Can not use the drawable directly in shared mode, need to decode it and create a new drawable.
-                Bitmap bitmap = BitmapFactory.decodeResource(mActivity.getResources(), resId);
-                Drawable finalDrawable = new BitmapDrawable(mActivity.getResources(), bitmap);
-
-                mLaunchScreenDialog = new Dialog(mLibContext, android.R.style.Theme_Holo_Light_NoActionBar);
-                if ((mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
-                    mLaunchScreenDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
+           public void run() {
+                int bgResId = mActivity.getResources().getIdentifier(
+                        "launchscreen_bg", "drawable", mActivity.getPackageName());
+                if (bgResId == 0) return;
+                Drawable bgDrawable = mActivity.getResources().getDrawable(bgResId);
+                if (bgDrawable == null) return;
+
+                mLaunchScreenDialog = new Dialog(mLibContext,
+                                                 android.R.style.Theme_Holo_Light_NoActionBar);
+                if ((mActivity.getWindow().getAttributes().flags &
+                     WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
+                    mLaunchScreenDialog.getWindow().setFlags(
+                            WindowManager.LayoutParams.FLAG_FULLSCREEN,
                             WindowManager.LayoutParams.FLAG_FULLSCREEN);
                 }
-                mLaunchScreenDialog.getWindow().setBackgroundDrawable(finalDrawable);
                 mLaunchScreenDialog.setOnKeyListener(new Dialog.OnKeyListener() {
                     @Override
                     public boolean onKey(DialogInterface arg0, int keyCode,
                             KeyEvent event) {
                         if (keyCode == KeyEvent.KEYCODE_BACK) {
-                            mLaunchScreenDialog.dismiss();
+                            performHideLaunchScreen();
                             mActivity.onBackPressed();
                         }
                         return true;
                     }
                 });
                 mLaunchScreenDialog.setOnShowListener(XWalkLaunchScreenManager.this);
+                mLaunchScreenDialog.setOnDismissListener(XWalkLaunchScreenManager.this);
+                // Set background
+                mLaunchScreenDialog.getWindow().setBackgroundDrawable(bgDrawable);
+                // Set foreground image
+                RelativeLayout root = getLaunchScreenLayout(imageBorderList);
+                if (root == null) return;
+                mLaunchScreenDialog.setContentView(root);
                 mLaunchScreenDialog.show();
+
+                // Change the layout depends on the orientation change.
+                mOrientationListener = new OrientationEventListener(mActivity,
+                        SensorManager.SENSOR_DELAY_NORMAL) {
+                    public void onOrientationChanged(int ori) {
+                        if (mLaunchScreenDialog == null || !mLaunchScreenDialog.isShowing()) {
+                            return;
+                        }
+                       int orientation = getScreenOrientation();
+                        if (orientation != mCurrentOrientation) {
+                            RelativeLayout root = getLaunchScreenLayout(imageBorderList);
+                            if (root == null) return;
+                            mLaunchScreenDialog.setContentView(root);
+                        }
+                    }
+                };
+                mOrientationListener.enable();
                 if (mReadyWhen == ReadyWhenType.CUSTOM) registerBroadcastReceiver();
             }
         };
@@ -115,6 +167,12 @@ public class XWalkLaunchScreenManager
     }
 
     @Override
+    public void onDismiss(DialogInterface dialog) {
+        mOrientationListener.disable();
+        mOrientationListener = null;
+    }
+
+    @Override
     public void onPageFinished(String url) {
         mPageLoadFinished = true;
         hideLaunchScreenWhenReady();
@@ -124,6 +182,359 @@ public class XWalkLaunchScreenManager
         return mIntentFilterStr;
     }
 
+    public int getScreenOrientation() {
+        // getResources().getConfiguration().orientation returns wrong value in some devices.
+        // Below is another way to calculate screen orientation.
+        Display display = mActivity.getWindowManager().getDefaultDisplay();
+        Point size = new Point();
+        display.getSize(size);
+        int orientation;
+        if (size.x < size.y) {
+            orientation = Configuration.ORIENTATION_PORTRAIT;
+        } else {
+            orientation = Configuration.ORIENTATION_LANDSCAPE;
+        }
+        return orientation;
+    }
+
+    private RelativeLayout getLaunchScreenLayout(String imageBorderList) {
+        // Parse the borders depends on orientation.
+        // imageBorderList format:"[default];[landscape];[portrait]"
+        String[] borders = imageBorderList.split(";");
+        // When there is no borders defined, display with no borders.
+        if (borders.length < 1) return parseImageBorder("");
+        int orientation = getScreenOrientation();
+        mCurrentOrientation = orientation;
+        if (borders.length >= 2 && orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            if (borders[1].equals("empty")) {
+                // Has launch_screen.landscape configured, but no image_border set.
+                // Display the iamge with no borders.
+                return parseImageBorder("");
+            } else if (borders[1].isEmpty()) {
+                // No launch_screen.landscape configured.
+                // Use launch_screen.default.
+                return parseImageBorder(borders[0]);
+            } else {
+                return parseImageBorder(borders[1]);
+            }
+        } else if (borders.length == 3 && orientation == Configuration.ORIENTATION_PORTRAIT) {
+            if (borders[2].equals("empty")) {
+                // Has launch_screen.portrait configured, but no image_border set.
+                // Display the iamge with no borders.
+                return parseImageBorder("");
+            } else if (borders[2].isEmpty()) {
+                // No launch_screen.portrait configured.
+                // Use launch_screen.default.
+                return parseImageBorder(borders[0]);
+            } else {
+                return parseImageBorder(borders[2]);
+            }
+        }
+
+        return parseImageBorder(borders[0]);
+    }
+
+    private int getSuitableSize(int maxSize, int divider) {
+        int finalSize = divider;
+        float minMod = divider;
+        for (; divider > 1; divider--) {
+            int mod = maxSize % divider;
+            // Found the suitable size.
+            if (mod == 0) {
+                finalSize = divider;
+                break;
+            }
+            // Record the best suitable one.
+            // If there is no mod==0 found, return the divider which min(mod).
+            if (mod < minMod) {
+                minMod = mod;
+                finalSize = divider;
+            }
+        }
+        return finalSize;
+    }
+
+    /**
+     * Get each section from 9-piece format image depends on the spec defined
+     * @param img The foreground image.
+     * @param x The position where the section start.
+     * @param y The position where the section start.
+     * @param width The width of the section.
+     * @param height The height of the section.
+     * @param mode The border type for this section.
+     * @param maxWidth When mode == ROUND, this will be used.
+     * @param maxHeight When mode == ROUND, this will be used.
+     * @return The ImageView for this section.
+     */
+    private ImageView getSubImageView(Bitmap img, int x, int y, int width, int height,
+                                      BorderModeType mode, int maxWidth, int maxHeight) {
+        if (img == null) return null;
+
+        if (width <= 0 || height <= 0) return null;
+
+        // Check whether the section is inside the foreground image.
+        Rect imgRect = new Rect(0, 0, img.getWidth(), img.getHeight());
+        Rect subRect = new Rect(x, y, x + width, y + height);
+        if (!imgRect.contains(subRect)) return null;
+
+        Bitmap subImage = Bitmap.createBitmap(img, x, y, width, height);
+        ImageView subImageView = new ImageView(mActivity);
+        BitmapDrawable drawable;
+        if (mode == BorderModeType.ROUND) {
+            int originW = subImage.getWidth();
+            int originH = subImage.getHeight();
+            int newW = originW;
+            int newH = originH;
+            // Scale down the sub image to let the last image not cropped when it's repeated.
+            if (maxWidth > 0) newW = getSuitableSize(maxWidth, originW);
+            if (maxHeight > 0) newH = getSuitableSize(maxHeight, originH);
+            // recreate the new scaled bitmap.
+            Bitmap resizedBitmap = Bitmap.createScaledBitmap(subImage, newW, newH, true);
+            // Treat as repeat mode.
+            subImage = resizedBitmap;
+            mode = BorderModeType.REPEAT;
+        }
+        if (mode == BorderModeType.REPEAT) {
+            drawable = new BitmapDrawable(mActivity.getResources(), subImage);
+            drawable.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
+            subImageView.setImageDrawable(drawable);
+            subImageView.setScaleType(ScaleType.FIT_XY);
+        } else if (mode == BorderModeType.STRETCH) {
+            subImageView.setImageBitmap(subImage);
+            subImageView.setScaleType(ScaleType.FIT_XY);
+        } else {
+            subImageView.setImageBitmap(subImage);
+        }
+
+        return subImageView;
+    }
+
+    private int getStatusBarHeight() {
+        int resourceId = mActivity.getResources().getIdentifier(
+                "status_bar_height", "dimen", "android");
+        if (resourceId > 0) {
+            return mActivity.getResources().getDimensionPixelSize(resourceId);
+        }
+        // If not found, return default one.
+        return 25;
+    }
+
+    private RelativeLayout parseImageBorder(String imageBorder) {
+        int topBorder = 0;
+        int rightBorder = 0;
+        int leftBorder = 0;
+        int bottomBorder = 0;
+        BorderModeType horizontalMode = BorderModeType.STRETCH;
+        BorderModeType verticalMode = BorderModeType.STRETCH;
+
+        if (imageBorder.equals("empty")) imageBorder = "";
+
+        // Parse the value of image_border.
+        String[] items = imageBorder.split(" ");
+        ArrayList<String> borders = new ArrayList<String>();
+        ArrayList<BorderModeType> modes = new ArrayList<BorderModeType>();
+        for (int i = 0; i < items.length; i++) {
+            String item = items[i];
+            if (item.endsWith("px")) {
+                borders.add(item.replaceAll("px", ""));
+            } else if (item.equals(BORDER_MODE_REPEAT)) {
+                modes.add(BorderModeType.REPEAT);
+            } else if (item.equals(BORDER_MODE_STRETCH)) {
+                modes.add(BorderModeType.STRETCH);
+            } else if (item.equals(BORDER_MODE_ROUND)) {
+                modes.add(BorderModeType.ROUND);
+            }
+        }
+        // Parse borders as defined by the spec.
+        try {
+            if (borders.size() == 1) {
+                topBorder = rightBorder = leftBorder = bottomBorder =
+                        Integer.valueOf(borders.get(0));
+            } else if (borders.size() == 2) {
+                topBorder = bottomBorder = Integer.valueOf(borders.get(0));
+                rightBorder = leftBorder = Integer.valueOf(borders.get(1));
+            } else if (borders.size() == 3) {
+                rightBorder = leftBorder = Integer.valueOf(borders.get(1));
+                topBorder = Integer.valueOf(borders.get(0));
+                bottomBorder = Integer.valueOf(borders.get(2));
+            } else if (borders.size() == 4) {
+                topBorder = Integer.valueOf(borders.get(0));
+                rightBorder = Integer.valueOf(borders.get(1));
+                leftBorder = Integer.valueOf(borders.get(2));
+                bottomBorder = Integer.valueOf(borders.get(3));
+            }
+        } catch (NumberFormatException e) {
+            topBorder = rightBorder = leftBorder = bottomBorder = 0;
+        }
+
+        // The border values are dpi from manifest.json, need to translate to px.
+        DisplayMetrics matrix = mActivity.getResources().getDisplayMetrics();
+        topBorder = (int)TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, topBorder, matrix);
+        rightBorder = (int)TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, rightBorder, matrix);
+        leftBorder = (int)TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, leftBorder, matrix);
+        bottomBorder = (int)TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, bottomBorder, matrix);
+
+        // Parse border mode as spec defined.
+        if (modes.size() == 1) {
+            horizontalMode = verticalMode = modes.get(0);
+        } else if (modes.size() == 2) {
+            horizontalMode = modes.get(0);
+            verticalMode = modes.get(1);
+        }
+
+        // Get foreground image
+        int imgResId = mActivity.getResources().getIdentifier(
+                       "launchscreen_img", "drawable", mActivity.getPackageName());
+        if (imgResId == 0) return null;
+        Bitmap img = BitmapFactory.decodeResource(mActivity.getResources(), imgResId);
+        if (img == null) return null;
+
+        // Create the 9-piece layout as spec defined.
+        RelativeLayout root = new RelativeLayout(mActivity);
+        root.setLayoutParams(new RelativeLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+        RelativeLayout.LayoutParams params;
+        ImageView subImageView;
+
+        // Get Screen width and height.
+        Display display = mActivity.getWindowManager().getDefaultDisplay();
+        Point size = new Point();
+        display.getSize(size);
+
+        // For non fullscreen, the height should substract status bar height
+        if ((mActivity.getWindow().getAttributes().flags &
+             WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0) {
+            size.y -= getStatusBarHeight();
+        }
+
+        // Image section-1 top left
+        subImageView = getSubImageView(img, 0, 0, leftBorder, topBorder, BorderModeType.NONE, 0, 0);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
+            root.addView(subImageView, params);
+        }
+
+        // Image section-2 top
+        subImageView = getSubImageView(img, leftBorder, 0, img.getWidth() - leftBorder
+                - rightBorder, topBorder, horizontalMode, size.x - leftBorder - rightBorder, 0);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.MATCH_PARENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
+            params.leftMargin = leftBorder;
+            params.rightMargin = rightBorder;
+            root.addView(subImageView, params);
+        }
+
+        // Image section-3 top right
+        subImageView = getSubImageView(img, img.getWidth() - rightBorder, 0,
+                rightBorder, topBorder, BorderModeType.NONE, 0, 0);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
+            root.addView(subImageView, params);
+        }
+
+        // Image section-4 left
+        subImageView = getSubImageView(img, 0, topBorder, leftBorder, img.getHeight()
+                - topBorder - bottomBorder, verticalMode, 0, size.y - topBorder - bottomBorder);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.MATCH_PARENT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
+            params.topMargin = topBorder;
+            params.bottomMargin = bottomBorder;
+            root.addView(subImageView, params);
+        }
+
+        // Image section-5 middle
+        subImageView = getSubImageView(img, leftBorder, topBorder, img.getWidth() - leftBorder - rightBorder,
+                img.getHeight() - topBorder - bottomBorder, BorderModeType.NONE, 0, 0);
+        if (subImageView != null) {
+            subImageView.setScaleType(ScaleType.FIT_XY);
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.MATCH_PARENT,
+                    RelativeLayout.LayoutParams.MATCH_PARENT);
+            params.leftMargin = leftBorder;
+            params.topMargin = topBorder;
+            params.rightMargin = rightBorder;
+            params.bottomMargin = bottomBorder;
+            root.addView(subImageView, params);
+        }
+
+        // Image section-6 right
+        subImageView = getSubImageView(img, img.getWidth() - rightBorder, topBorder, rightBorder,
+                img.getHeight() - topBorder - bottomBorder, verticalMode, 0,
+                size.y - topBorder - bottomBorder);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.MATCH_PARENT);
+            params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
+            params.topMargin = topBorder;
+            params.bottomMargin = bottomBorder;
+            root.addView(subImageView, params);
+        }
+
+        // Image section-7 bottom left
+        subImageView = getSubImageView(img, 0, img.getHeight() - bottomBorder,
+                leftBorder, bottomBorder, BorderModeType.NONE, 0, 0);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
+            root.addView(subImageView, params);
+        }
+
+        // Image section-8 bottom
+        subImageView = getSubImageView(img, leftBorder, img.getHeight() - bottomBorder,
+                img.getWidth() - leftBorder - rightBorder, bottomBorder, horizontalMode,
+                size.x - leftBorder - rightBorder, 0);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.MATCH_PARENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            params.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
+            params.leftMargin = leftBorder;
+            params.rightMargin = rightBorder;
+            root.addView(subImageView, params);
+        }
+
+        // Image section-9 bottom right
+        subImageView = getSubImageView(img, img.getWidth() - rightBorder,
+                img.getHeight() - bottomBorder, rightBorder, bottomBorder,
+               BorderModeType.NONE, 0, 0);
+        if (subImageView != null) {
+            params = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
+            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
+            root.addView(subImageView, params);
+        }
+        return root;
+    }
+
     private void registerBroadcastReceiver() {
         IntentFilter intentFilter = new IntentFilter(mIntentFilterStr);
         mLaunchScreenReadyWhenReceiver = new BroadcastReceiver() {
index 7cbec47..0d793dc 100644 (file)
@@ -15,7 +15,9 @@ import org.chromium.components.navigation_interception.NavigationParams;
 
 import org.xwalk.core.XWalkNavigationHandler;
 
-// TODO(yongsheng): remove public modifier.
+/**
+ * @hide
+ */
 public class XWalkNavigationHandlerImpl implements XWalkNavigationHandler {
     private static final String TAG = "XWalkNavigationHandlerImpl";
 
index 929a260..6547772 100644 (file)
@@ -77,10 +77,12 @@ public final class XWalkNavigationHistory implements Cloneable, Serializable {
     }
 
     /**
-     * The direction for navigation.
+     * The direction for web page navigation.
      */
     public enum Direction {
+        /** the backward direction for web page navigation. */
         BACKWARD,
+        /** the forward direction for web page navigation. */
         FORWARD
     }
 
@@ -94,8 +96,10 @@ public final class XWalkNavigationHistory implements Cloneable, Serializable {
         switch(direction) {
             case FORWARD:
                 mXWalkView.navigateTo(steps);
+                break;
             case BACKWARD:
                 mXWalkView.navigateTo(-steps);
+                break;
             default:
                 break;
         }
index 48cf75f..a879a60 100644 (file)
@@ -7,7 +7,7 @@ package org.xwalk.core;
 import org.chromium.content.browser.NavigationEntry;
 
 /**
- * Represent a navigation item and managed in XWalkNavigationHistory.
+ * This class represents a navigation item and is managed in XWalkNavigationHistory.
  */
 public final class XWalkNavigationItem implements Cloneable {
     private NavigationEntry mEntry;
index dbc6a73..3e796a1 100644 (file)
@@ -23,7 +23,9 @@ import org.xwalk.core.XWalkContentsClientBridge;
 import org.xwalk.core.XWalkNotificationService;
 import org.xwalk.core.XWalkView;
 
-// TODO(yongsheng): remove public modifier.
+/**
+ * @hide
+ */
 public class XWalkNotificationServiceImpl implements XWalkNotificationService {
     private static final String TAG = "XWalkNotificationServiceImpl";
 
index d2cf5df..3423876 100644 (file)
@@ -9,7 +9,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
- * This class is not thread-safe and must be called on the UI thread.
+ * This class represents the preferences and could be set by callers.
+ * It is not thread-safe and must be called on the UI thread.
  * Afterwards, the preference could be read from all threads and can impact
  * all XWalkView instances.
  */
@@ -42,7 +43,7 @@ public final class XWalkPreferences {
     }
 
     /**
-     * Get a preference value into Crosswalk. An exception will be thrown if
+     * Get a preference value from Crosswalk. An exception will be thrown if
      * the key for the preference is not valid.
      * @param key the string name of the key.
      * @return true if it's enabled.
index 4490600..63fa3a7 100644 (file)
@@ -4,12 +4,57 @@
 
 package org.xwalk.core;
 
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.View;
 import android.webkit.WebResourceResponse;
 
 /**
- * This interface notifies the embedder resource events/callbacks.
+ * This class notifies the embedder resource events/callbacks.
  */
 public class XWalkResourceClient {
+    /** Success */
+    public static final int ERROR_OK = 0;
+    /** Generic error */
+    public static final int ERROR_UNKNOWN = -1;
+    /** Server or proxy hostname lookup failed */
+    public static final int ERROR_HOST_LOOKUP = -2;
+    /** Unsupported authentication scheme (not basic or digest) */
+    public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
+    /** User authentication failed on server */
+    public static final int ERROR_AUTHENTICATION = -4;
+    /** User authentication failed on proxy */
+    public static final int ERROR_PROXY_AUTHENTICATION = -5;
+    /** Failed to connect to the server */
+    public static final int ERROR_CONNECT = -6;
+    /** Failed to read or write to the server */
+    public static final int ERROR_IO = -7;
+    /** Connection timed out */
+    public static final int ERROR_TIMEOUT = -8;
+    /** Too many redirects */
+    public static final int ERROR_REDIRECT_LOOP = -9;
+    /** Unsupported URI scheme */
+    public static final int ERROR_UNSUPPORTED_SCHEME = -10;
+    /** Failed to perform SSL handshake */
+    public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
+    /** Malformed URL */
+    public static final int ERROR_BAD_URL = -12;
+    /** Generic file error */
+    public static final int ERROR_FILE = -13;
+    /** File not found */
+    public static final int ERROR_FILE_NOT_FOUND = -14;
+    /** Too many requests during this load */
+    public static final int ERROR_TOO_MANY_REQUESTS = -15;
+
+    /**
+     * Constructor.
+     * @param view the owner XWalkView instance.
+     */
+    public XWalkResourceClient(XWalkView view) {
+        // Keep the above parameter for future use.
+    }
+
     /**
      * Notify the client that the XWalkView will load the resource specified
      * by the given url.
@@ -31,7 +76,7 @@ public class XWalkResourceClient {
     /**
      * Notify the client the progress info of loading a specific url.
      * @param view the owner XWalkView instance.
-     * @param url the loading process in percent.
+     * @param progressInPercent the loading process in percent.
      */
     public void onProgressChanged(XWalkView view, int progressInPercent) {
     }
@@ -63,6 +108,17 @@ public class XWalkResourceClient {
      */
     public void onReceivedLoadError(XWalkView view, int errorCode, String description,
             String failingUrl) {
-        // TODO(yongsheng): Need to define errorCode.
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(view.getContext());
+        dialogBuilder.setTitle(android.R.string.dialog_alert_title)
+                .setMessage(description)
+                .setCancelable(false)
+                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        dialog.dismiss();
+                    }
+                });
+        AlertDialog dialog = dialogBuilder.create();
+        dialog.show();
     }
 }
diff --git a/src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkResourceClientImpl.java b/src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkResourceClientImpl.java
deleted file mode 100644 (file)
index be5829e..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.view.View;
-
-/**
- * It's the default implementation class for XWalkResourceClient.
- */
-public class XWalkResourceClientImpl extends XWalkResourceClient {
-    private Context mContext;
-    private AlertDialog mDialog;
-    private XWalkView mXWalkView;
-
-    public XWalkResourceClientImpl(Context context, XWalkView view) {
-        mContext = context;
-        mXWalkView = view;
-    }
-
-    @Override
-    public void onReceivedLoadError(XWalkView view, int errorCode,
-            String description, String failingUrl) {
-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
-        dialogBuilder.setTitle(android.R.string.dialog_alert_title)
-                .setMessage(description)
-                .setCancelable(false)
-                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        dialog.dismiss();
-                    }
-                });
-        mDialog = dialogBuilder.create();
-        mDialog.show();
-    }
-}
index 6115d68..a77515f 100644 (file)
@@ -16,6 +16,9 @@ import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
 import org.chromium.base.ThreadUtils;
 
+/**
+ * @hide
+ */
 @JNINamespace("xwalk")
 public class XWalkSettings {
 
@@ -62,7 +65,7 @@ public class XWalkSettings {
     private static boolean sAppCachePathIsSet = false;
 
     // The native side of this object.
-    private int mNativeXWalkSettings = 0;
+    private long mNativeXWalkSettings = 0;
 
     // A flag to avoid sending superfluous synchronization messages.
     private boolean mIsUpdateWebkitPrefsMessagePending = false;
@@ -134,7 +137,7 @@ public class XWalkSettings {
         }
     }
 
-    public XWalkSettings(Context context, int nativeWebContents,
+    public XWalkSettings(Context context, long nativeWebContents,
             boolean isAccessFromFileURLsGrantedByDefault) {
         ThreadUtils.assertOnUiThread();
         mContext = context;
@@ -155,7 +158,7 @@ public class XWalkSettings {
         setWebContents(nativeWebContents);
     }
 
-    void setWebContents(int nativeWebContents) {
+    void setWebContents(long nativeWebContents) {
         synchronized (mXWalkSettingsLock) {
             if (mNativeXWalkSettings != 0) {
                 nativeDestroy(mNativeXWalkSettings);
@@ -170,7 +173,7 @@ public class XWalkSettings {
     }
 
     @CalledByNative
-    private void nativeXWalkSettingsGone(int nativeXWalkSettings) {
+    private void nativeXWalkSettingsGone(long nativeXWalkSettings) {
         assert mNativeXWalkSettings != 0 && mNativeXWalkSettings == nativeXWalkSettings;
         mNativeXWalkSettings = 0;
     }
@@ -585,7 +588,7 @@ public class XWalkSettings {
     }
 
     /**
-     * @returns the default User-Agent used by each ContentViewCore instance, i.e. unless
+     * @return returns the default User-Agent used by each ContentViewCore instance, i.e. unless
      * overridden by {@link #setUserAgentString()}
      */
     public static String getDefaultUserAgent() {
@@ -653,15 +656,15 @@ public class XWalkSettings {
         }
     }
 
-    private native int nativeInit(int webContentsPtr);
+    private native long nativeInit(long webContentsPtr);
 
-    private native void nativeDestroy(int nativeXWalkSettings);
+    private native void nativeDestroy(long nativeXWalkSettings);
 
     private static native String nativeGetDefaultUserAgent();
 
-    private native void nativeUpdateEverythingLocked(int nativeXWalkSettings);
+    private native void nativeUpdateEverythingLocked(long nativeXWalkSettings);
 
-    private native void nativeUpdateUserAgent(int nativeXWalkSettings);
+    private native void nativeUpdateUserAgent(long nativeXWalkSettings);
 
-    private native void nativeUpdateWebkitPreferences(int nativeXWalkSettings);
+    private native void nativeUpdateWebkitPreferences(long nativeXWalkSettings);
 }
index b764553..af86daf 100644 (file)
@@ -4,13 +4,64 @@
 
 package org.xwalk.core;
 
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
 import android.net.Uri;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
 import android.webkit.ValueCallback;
+import android.widget.EditText;
 
 /**
  * This class notifies the embedder UI events/callbacks.
  */
 public class XWalkUIClient {
+
+    // Strings for displaying Dialog.
+    private static String mJSAlertTitle;
+    private static String mJSConfirmTitle;
+    private static String mJSPromptTitle;
+    private static String mOKButton;
+    private static String mCancelButton;
+
+    private Context mContext;
+    private AlertDialog mDialog;
+    private EditText mPromptText;
+    private int mSystemUiFlag;
+    private View mDecorView;
+    private XWalkView mXWalkView;
+    private boolean mOriginalFullscreen;
+
+    /**
+     * Constructor.
+     * @param view the owner XWalkView instance.
+     */
+    public XWalkUIClient(XWalkView view) {
+        mContext = view.getContext();
+        mDecorView = view.getActivity().getWindow().getDecorView();
+        if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
+            mSystemUiFlag = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+                    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+        }
+        mXWalkView = view;
+        initResources();
+    }
+
+    private void initResources() {
+        if (mJSAlertTitle != null) return;
+        mJSAlertTitle = mContext.getString(R.string.js_alert_title);
+        mJSConfirmTitle = mContext.getString(R.string.js_confirm_title);
+        mJSPromptTitle = mContext.getString(R.string.js_prompt_title);
+        mOKButton = mContext.getString(android.R.string.ok);
+        mCancelButton = mContext.getString(android.R.string.cancel);
+    }
+
     /**
      * Request display and focus for this XWalkView.
      * @param view the owner XWalkView instance.
@@ -23,15 +74,22 @@ public class XWalkUIClient {
      * @param view the owner XWalkView instance.
      */
     public void onJavascriptCloseWindow(XWalkView view) {
+        if (view != null && view.getActivity() != null) {
+            view.getActivity().finish();
+        }
     }
 
     /**
      * The type of JavaScript modal dialog.
      */
     public enum JavascriptMessageType {
+        /** JavaScript alert dialog. */
         JAVASCRIPT_ALERT,
+        /** JavaScript confirm dialog. */
         JAVASCRIPT_CONFIRM,
+        /** JavaScript prompt dialog. */
         JAVASCRIPT_PROMPT,
+        /** JavaScript dialog for a window-before-unload notification. */
         JAVASCRIPT_BEFOREUNLOAD
     }
 
@@ -46,6 +104,20 @@ public class XWalkUIClient {
      */
     public boolean onJavascriptModalDialog(XWalkView view, JavascriptMessageType type, String url,
             String message, String defaultValue, XWalkJavascriptResult result) {
+        switch(type) {
+            case JAVASCRIPT_ALERT:
+                return onJsAlert(view, url, message, result);
+            case JAVASCRIPT_CONFIRM:
+                return onJsConfirm(view, url, message, result);
+            case JAVASCRIPT_PROMPT:
+                return onJsPrompt(view, url, message, defaultValue, result);
+            case JAVASCRIPT_BEFOREUNLOAD:
+                // Reuse onJsConfirm to show the dialog.
+                return onJsConfirm(view, url, message, result);
+            default:
+                break;
+        }
+        assert(false);
         return false;
     }
 
@@ -55,12 +127,52 @@ public class XWalkUIClient {
      * @param enterFullscreen true if it has entered fullscreen mode.
      */
     public void onFullscreenToggled(XWalkView view, boolean enterFullscreen) {
+        Activity activity = view.getActivity();
+        if (enterFullscreen) {
+            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
+                mSystemUiFlag = mDecorView.getSystemUiVisibility();
+                mDecorView.setSystemUiVisibility(
+                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+                        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+                        View.SYSTEM_UI_FLAG_FULLSCREEN |
+                        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+            } else {
+                if ((activity.getWindow().getAttributes().flags &
+                        WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
+                    mOriginalFullscreen = true;
+                } else {
+                    mOriginalFullscreen = false;
+                }
+                if (!mOriginalFullscreen) {
+                    activity.getWindow().setFlags(
+                            WindowManager.LayoutParams.FLAG_FULLSCREEN,
+                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
+                }
+            }
+        } else {
+            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
+                mDecorView.setSystemUiVisibility(mSystemUiFlag);
+            } else {
+                // Clear the activity fullscreen flag.
+                if (!mOriginalFullscreen) {
+                    activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+                }
+            }
+        }
     }
 
     /**
      * Tell the client to open a file chooser.
      * @param view the owner XWalkView instance.
-     * @param uploadFile the callback class to handle the result from caller.
+     * @param uploadFile the callback class to handle the result from caller. It MUST
+     *        be invoked in all cases. Leave it not invoked will block all following
+     *        requests to open file chooser.
+     * @param acceptType value of the 'accept' attribute of the input tag associated
+     *        with this file picker.
+     * @param capture value of the 'capture' attribute of the input tag associated
+     *        with this file picker
      */
     public void openFileChooser(XWalkView view, ValueCallback<Uri> uploadFile,
             String acceptType, String capture) {
@@ -75,4 +187,100 @@ public class XWalkUIClient {
      */
     public void onScaleChanged(XWalkView view, float oldScale, float newScale) {
     }
+
+    private boolean onJsAlert(XWalkView view, String url, String message,
+            XWalkJavascriptResult result) {
+        final XWalkJavascriptResult fResult = result;
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+        dialogBuilder.setTitle(mJSAlertTitle)
+                .setMessage(message)
+                .setCancelable(true)
+                .setPositiveButton(mOKButton, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        fResult.confirm();
+                        dialog.dismiss();
+                    }
+                }).setOnKeyListener(new DialogInterface.OnKeyListener() {
+                    @Override
+                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                        if (keyCode == KeyEvent.KEYCODE_BACK) {
+                            fResult.confirm();
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                });
+        mDialog = dialogBuilder.create();
+        mDialog.show();
+        return false;
+    }
+
+    private boolean onJsConfirm(XWalkView view, String url, String message,
+            XWalkJavascriptResult result) {
+        final XWalkJavascriptResult fResult = result;
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+        dialogBuilder.setTitle(mJSConfirmTitle)
+                .setMessage(message)
+                .setCancelable(true)
+                .setPositiveButton(mOKButton, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        fResult.confirm();
+                        dialog.dismiss();
+                    }
+                })
+                .setNegativeButton(mCancelButton, null)
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    @Override
+                    public void onCancel(DialogInterface dialog) {
+                        fResult.cancel();
+                    }
+                }).setOnKeyListener(new DialogInterface.OnKeyListener() {
+                    @Override
+                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                        if (keyCode == KeyEvent.KEYCODE_BACK) {
+                            fResult.confirm();
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                });
+        mDialog = dialogBuilder.create();
+        mDialog.show();
+        return false;
+    }
+
+    private boolean onJsPrompt(XWalkView view, String url, String message,
+            String defaultValue, XWalkJavascriptResult result) {
+        final XWalkJavascriptResult fResult = result;
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+        dialogBuilder.setTitle(mJSPromptTitle)
+                .setMessage(message)
+                .setPositiveButton(mOKButton, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        fResult.confirmWithResult(mPromptText.getText().toString());
+                        dialog.dismiss();
+                    }
+                })
+                .setNegativeButton(mCancelButton, null)
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    @Override
+                    public void onCancel(DialogInterface dialog) {
+                        fResult.cancel();
+                    }
+                });
+        mPromptText = new EditText(mContext);
+        mPromptText.setVisibility(View.VISIBLE);
+        mPromptText.setText(defaultValue);
+        mPromptText.selectAll();
+
+        dialogBuilder.setView(mPromptText);
+        mDialog = dialogBuilder.create();
+        mDialog.show();
+        return false;
+    }
 }
diff --git a/src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkUIClientImpl.java b/src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkUIClientImpl.java
deleted file mode 100644 (file)
index 4276e1a..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright (c) 2013 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;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.net.Uri;
-import android.os.Build.VERSION;
-import android.os.Build.VERSION_CODES;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.webkit.ValueCallback;
-import android.widget.EditText;
-
-/**
- * This is the implementation of XWalkUIClient if callers don't specify one.
- */
-public class XWalkUIClientImpl extends XWalkUIClient {
-
-    // Strings for displaying Dialog.
-    private static String mJSAlertTitle;
-    private static String mJSConfirmTitle;
-    private static String mJSPromptTitle;
-    private static String mOKButton;
-    private static String mCancelButton;
-
-    private Context mContext;
-    private AlertDialog mDialog;
-    private EditText mPromptText;
-    private int mSystemUiFlag;
-    private View mDecorView;
-    private XWalkView mXWalkView;
-    private boolean mOriginalFullscreen;
-
-    public XWalkUIClientImpl(Context context, XWalkView view) {
-        mContext = context;
-        mDecorView = view.getActivity().getWindow().getDecorView();
-        if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
-            mSystemUiFlag = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
-                    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
-                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-        }
-        mXWalkView = view;
-        initResources(context);
-    }
-
-    private static void initResources(Context context) {
-        if (mJSAlertTitle != null) return;
-        mJSAlertTitle = context.getString(R.string.js_alert_title);
-        mJSConfirmTitle = context.getString(R.string.js_confirm_title);
-        mJSPromptTitle = context.getString(R.string.js_prompt_title);
-        mOKButton = context.getString(android.R.string.ok);
-        mCancelButton = context.getString(android.R.string.cancel);
-    }
-
-    @Override
-    public void onJavascriptCloseWindow(XWalkView view) {
-        if (view != null && view.getActivity() != null) {
-            view.getActivity().finish();
-        }
-    }
-
-    @Override
-    public boolean onJavascriptModalDialog(XWalkView view, JavascriptMessageType type, String url,
-            String message, String defaultValue, XWalkJavascriptResult result) {
-        switch(type) {
-            case JAVASCRIPT_ALERT:
-                return onJsAlert(view, url, message, result);
-            case JAVASCRIPT_CONFIRM:
-                return onJsConfirm(view, url, message, result);
-            case JAVASCRIPT_PROMPT:
-                return onJsPrompt(view, url, message, defaultValue, result);
-            case JAVASCRIPT_BEFOREUNLOAD:
-                // Reuse onJsConfirm to show the dialog.
-                return onJsConfirm(view, url, message, result);
-            default:
-                break;
-        }
-        assert(false);
-        return false;
-    }
-
-    private boolean onJsAlert(XWalkView view, String url, String message,
-            XWalkJavascriptResult result) {
-        final XWalkJavascriptResult fResult = result;
-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
-        dialogBuilder.setTitle(mJSAlertTitle)
-                .setMessage(message)
-                .setCancelable(true)
-                .setPositiveButton(mOKButton, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        fResult.confirm();
-                        dialog.dismiss();
-                    }
-                }).setOnKeyListener(new DialogInterface.OnKeyListener() {
-                    @Override
-                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
-                        if (keyCode == KeyEvent.KEYCODE_BACK) {
-                            fResult.confirm();
-                            return false;
-                        } else {
-                            return true;
-                        }
-                    }
-                });
-        mDialog = dialogBuilder.create();
-        mDialog.show();
-        return false;
-    }
-
-    private boolean onJsConfirm(XWalkView view, String url, String message,
-            XWalkJavascriptResult result) {
-        final XWalkJavascriptResult fResult = result;
-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
-        dialogBuilder.setTitle(mJSConfirmTitle)
-                .setMessage(message)
-                .setCancelable(true)
-                .setPositiveButton(mOKButton, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        fResult.confirm();
-                        dialog.dismiss();
-                    }
-                })
-                .setNegativeButton(mCancelButton, null)
-                .setOnCancelListener(new DialogInterface.OnCancelListener() {
-                    @Override
-                    public void onCancel(DialogInterface dialog) {
-                        fResult.cancel();
-                    }
-                }).setOnKeyListener(new DialogInterface.OnKeyListener() {
-                    @Override
-                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
-                        if (keyCode == KeyEvent.KEYCODE_BACK) {
-                            fResult.confirm();
-                            return false;
-                        } else {
-                            return true;
-                        }
-                    }
-                });
-        mDialog = dialogBuilder.create();
-        mDialog.show();
-        return false;
-    }
-
-    private boolean onJsPrompt(XWalkView view, String url, String message,
-            String defaultValue, XWalkJavascriptResult result) {
-        final XWalkJavascriptResult fResult = result;
-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
-        dialogBuilder.setTitle(mJSPromptTitle)
-                .setMessage(message)
-                .setPositiveButton(mOKButton, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        fResult.confirmWithResult(mPromptText.getText().toString());
-                        dialog.dismiss();
-                    }
-                })
-                .setNegativeButton(mCancelButton, null)
-                .setOnCancelListener(new DialogInterface.OnCancelListener() {
-                    @Override
-                    public void onCancel(DialogInterface dialog) {
-                        fResult.cancel();
-                    }
-                });
-        mPromptText = new EditText(mContext);
-        mPromptText.setVisibility(View.VISIBLE);
-        mPromptText.setText(defaultValue);
-        mPromptText.selectAll();
-
-        dialogBuilder.setView(mPromptText);
-        mDialog = dialogBuilder.create();
-        mDialog.show();
-        return false;
-    }
-
-    @Override
-    public void onFullscreenToggled(XWalkView view, boolean enterFullscreen) {
-        Activity activity = view.getActivity();
-        if (enterFullscreen) {
-            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
-                mSystemUiFlag = mDecorView.getSystemUiVisibility();
-                mDecorView.setSystemUiVisibility(
-                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
-                        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
-                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
-                        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
-                        View.SYSTEM_UI_FLAG_FULLSCREEN |
-                        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
-            } else {
-                if ((activity.getWindow().getAttributes().flags &
-                        WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
-                    mOriginalFullscreen = true;
-                } else {
-                    mOriginalFullscreen = false;
-                }
-                if (!mOriginalFullscreen) {
-                    activity.getWindow().setFlags(
-                            WindowManager.LayoutParams.FLAG_FULLSCREEN,
-                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
-                }
-            }
-        } else {
-            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
-                mDecorView.setSystemUiVisibility(mSystemUiFlag);
-            } else {
-                // Clear the activity fullscreen flag.
-                if (!mOriginalFullscreen) {
-                    activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-                }
-            }
-        }
-    }
-}
index fe3d91d..8cd941d 100644 (file)
@@ -5,18 +5,27 @@
 package org.xwalk.core;
 
 import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ApplicationErrorReport;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Looper;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.ViewGroup;
-import android.webkit.WebSettings;
 import android.webkit.ValueCallback;
 import android.widget.FrameLayout;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+
 import org.xwalk.core.extension.XWalkExtensionManager;
 
 /**
@@ -36,15 +45,22 @@ import org.xwalk.core.extension.XWalkExtensionManager;
  * It already includes all newly created Web APIs from Crosswalk like Presentation,
  * DeviceCapabilities, etc..
  */
-public class XWalkView extends FrameLayout {
+public class XWalkView extends android.widget.FrameLayout {
+
+    protected static final String PLAYSTORE_DETAIL_URI = "market://details?id=";
 
     private XWalkContent mContent;
     private Activity mActivity;
     private Context mContext;
     private XWalkExtensionManager mExtensionManager;
 
+    /** Normal reload mode as default. */
+    public static final int RELOAD_NORMAL = 0;
+    /** Reload mode with bypassing the cache. */
+    public static final int RELOAD_IGNORE_CACHE = 1;
+
     /**
-     * Constructors for inflating via XML.
+     * Constructor for inflating via XML.
      * @param context  a Context object used to access application assets.
      * @param attrs    an AttributeSet passed to our parent.
      */
@@ -57,7 +73,7 @@ public class XWalkView extends FrameLayout {
     }
 
     /**
-     * Constructors for Crosswalk runtime. In shared mode, context isi
+     * Constructor for Crosswalk runtime. In shared mode, context isi
      * different from activity. In embedded mode, they're same.
      * @param context  a Context object used to access application assets
      * @param activity the activity for this XWalkView.
@@ -75,6 +91,8 @@ public class XWalkView extends FrameLayout {
     /**
      * Get the current activity passed from callers. It's never null.
      * @return the activity instance passed from callers.
+     *
+     * @hide
      */
     public Activity getActivity() {
         if (mActivity != null) {
@@ -89,6 +107,9 @@ public class XWalkView extends FrameLayout {
     }
 
     // TODO(yongsheng): we should remove this since we have getContext()?
+    /**
+     * @hide
+     */
     public Context getViewContext() {
         return mContext;
     }
@@ -99,7 +120,67 @@ public class XWalkView extends FrameLayout {
         XWalkInternalResources.resetIds(context);
 
         // Intialize library, paks and others.
-        XWalkViewDelegate.init(this);
+        try {
+            XWalkViewDelegate.init(this);
+        } catch (UnsatisfiedLinkError e) {
+            final UnsatisfiedLinkError err = e;
+            final Activity activity = getActivity();
+            final String packageName = context.getPackageName();
+            String missingArch = XWalkViewDelegate.isRunningOnIA() ? "Intel" : "ARM";
+            final String message =
+                    context.getString(R.string.cpu_arch_mismatch_message, missingArch);
+
+            AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+            builder.setTitle(R.string.cpu_arch_mismatch_title)
+                    .setMessage(message)
+                    .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface dialog) {
+                            activity.finish();
+                        }
+                    }).setPositiveButton(R.string.goto_store_button_label,
+                            new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            activity.startActivity(new Intent(Intent.ACTION_VIEW,
+                                    Uri.parse(PLAYSTORE_DETAIL_URI + packageName)));
+                            activity.finish();
+                        }
+                    }).setNeutralButton(R.string.report_feedback_button_label,
+                            new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            ApplicationErrorReport report = new ApplicationErrorReport();
+                            report.type = ApplicationErrorReport.TYPE_CRASH;
+                            report.packageName = report.processName = packageName;
+
+                            ApplicationErrorReport.CrashInfo crash =
+                                    new ApplicationErrorReport.CrashInfo();
+                            crash.exceptionClassName = err.getClass().getSimpleName();
+                            crash.exceptionMessage = "CPU architecture mismatch";
+                            StringWriter writer = new StringWriter();
+                            PrintWriter print = new PrintWriter(writer);
+                            err.printStackTrace(print);
+                            crash.stackTrace = writer.toString();
+                            StackTraceElement stack = err.getStackTrace()[0];
+                            crash.throwClassName = stack.getClassName();
+                            crash.throwFileName = stack.getFileName();
+                            crash.throwLineNumber = stack.getLineNumber();
+                            crash.throwMethodName = stack.getMethodName();
+
+                            report.crashInfo = crash;
+                            report.systemApp = false;
+                            report.time = System.currentTimeMillis();
+
+                            Intent intent = new Intent(Intent.ACTION_APP_ERROR);
+                            intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
+                            activity.startActivity(intent);
+                            activity.finish();
+                        }
+                    });
+            builder.create().show();
+            return;
+        }
 
         initXWalkContent(context, attrs);
     }
@@ -113,15 +194,15 @@ public class XWalkView extends FrameLayout {
 
 
         // Set default XWalkClientImpl.
-        setXWalkClient(new XWalkClient(context, this));
+        setXWalkClient(new XWalkClient(this));
         // Set default XWalkWebChromeClient and DownloadListener. The default actions
         // are provided via the following clients if special actions are not needed.
-        setXWalkWebChromeClient(new XWalkWebChromeClient(context, this));
+        setXWalkWebChromeClient(new XWalkWebChromeClient(this));
 
         // Set with internal implementation. Could be overwritten by embedders'
         // setting.
-        setUIClient(new XWalkUIClientImpl(context, this));
-        setResourceClient(new XWalkResourceClientImpl(context, this));
+        setUIClient(new XWalkUIClient(this));
+        setResourceClient(new XWalkResourceClient(this));
 
         setDownloadListener(new XWalkDownloadListenerImpl(context));
         setNavigationHandler(new XWalkNavigationHandlerImpl(context));
@@ -134,41 +215,57 @@ public class XWalkView extends FrameLayout {
     }
 
     /**
-     * Load a web page/app from a given base URL or a content. If content is
-     * specified, load the web page/app from the content. If it's null, try to
-     * load the content from the baseUrl.
-     * @param baseUrl the base url for web page/app.
+     * Load a web page/app from a given base URL or a content.
+     * If url is null or empty and content is null or empty, then this function
+     * will do nothing.
+     * If content is not null, load the web page/app from the content.
+     * If content is not null and the url is not set, return "about:blank" ifi
+     * calling {@link XWalkView#getUrl()}.
+     * If content is null, try to load the content from the url.
+     *
+     * It supports URL schemes like 'http:', 'https:' and 'file:'.
+     * It can also load files from Android assets, e.g. 'file:///android_asset/'.
+     * @param url the url for web page/app.
      * @param content the content for the web page/app. Could be empty.
      */
-    public void load(String baseUrl, String content) {
+    public void load(String url, String content) {
+        if (mContent == null) return;
         checkThreadSafety();
-        // TODO(yongsheng): enable to use content.
-        mContent.loadUrl(baseUrl);
+        mContent.loadUrl(url, content);
     }
 
     /**
-     * Load a web app from a given manifest.json file. The content must not be
-     * empty.
-     * @param baseUrl the base url for manifest.json.
+     * Load a web app from a given manifest.json file. If content is not null,
+     * load the manifest.json from the content. If content is null, try to load
+     * the manifest.json from the url. Note that url should not be null if the
+     * launched path defined in manifest.json is relative.
+     *
+     * It supports URL schemes like 'http:', 'https:' and 'file:'.
+     * It can also load files from Android assets, e.g. 'file:///android_asset/'.
+     * @param url the url for manifest.json.
      * @param content the content for manifest.json.
      */
-    public void loadAppFromManifest(String baseUrl, String content) {
-        mContent.loadAppFromManifest(baseUrl, content);
+    public void loadAppFromManifest(String url, String content) {
+        if (mContent == null) return;
+        checkThreadSafety();
+        mContent.loadAppFromManifest(url, content);
     }
 
     /**
-     * Reload a web app with a given reload mode.
+     * Reload a web app with a given mode.
+     * @param mode the reload mode.
      */
-    // TODO(yongsheng): add reload modes here.
-    public void reload() {
+    public void reload(int mode) {
+        if (mContent == null) return;
         checkThreadSafety();
-        mContent.reload();
+        mContent.reload(mode);
     }
 
     /**
      * Stop current loading progress.
      */
     public void stopLoading() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.stopLoading();
     }
@@ -179,6 +276,7 @@ public class XWalkView extends FrameLayout {
      * @return the url for current web page/app.
      */
     public String getUrl() {
+        if (mContent == null) return null;
         checkThreadSafety();
         return mContent.getUrl();
     }
@@ -189,6 +287,7 @@ public class XWalkView extends FrameLayout {
      * @return the title for current web page/app.
      */
     public String getTitle() {
+        if (mContent == null) return null;
         checkThreadSafety();
         return mContent.getTitle();
     }
@@ -198,6 +297,7 @@ public class XWalkView extends FrameLayout {
      * @return the original url.
      */
     public String getOriginalUrl() {
+        if (mContent == null) return null;
         checkThreadSafety();
         return mContent.getOriginalUrl();
     }
@@ -208,15 +308,20 @@ public class XWalkView extends FrameLayout {
      * @return the navigation history.
      */
     public XWalkNavigationHistory getNavigationHistory() {
+        if (mContent == null) return null;
+        checkThreadSafety();
         return mContent.getNavigationHistory();
     }
 
     /**
      * Injects the supplied Java object into this XWalkView.
+     * Each method defined in the class of the object should be
+     * marked with {@link JavascriptInterface} if it's called by JavaScript.
      * @param object the supplied Java object, called by JavaScript.
      * @param name the name injected in JavaScript.
      */
     public void addJavascriptInterface(Object object, String name) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.addJavascriptInterface(object, name);
     }
@@ -226,7 +331,8 @@ public class XWalkView extends FrameLayout {
      * @param script the JavaScript string.
      * @param callback the callback to handle the evaluated result.
      */
-    void evaluateJavascript(String script, ValueCallback<String> callback) {
+    public void evaluateJavascript(String script, ValueCallback<String> callback) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.evaluateJavascript(script, callback);
     }
@@ -237,6 +343,7 @@ public class XWalkView extends FrameLayout {
      * @param includeDiskFiles indicate whether to clear disk files for cache.
      */
     public void clearCache(boolean includeDiskFiles) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.clearCache(includeDiskFiles);
     }
@@ -246,6 +353,7 @@ public class XWalkView extends FrameLayout {
      * @return true if any HTML element is occupying the whole screen.
      */
     public boolean hasEnteredFullscreen() {
+        if (mContent == null) return false;
         checkThreadSafety();
         return mContent.hasEnteredFullscreen();
     }
@@ -255,6 +363,7 @@ public class XWalkView extends FrameLayout {
      * in fullscreen.
      */
     public void leaveFullscreen() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.exitFullscreen();
     }
@@ -264,6 +373,7 @@ public class XWalkView extends FrameLayout {
      * when the activity for this view is paused.
      */
     public void pauseTimers() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.pauseTimers();
     }
@@ -273,6 +383,7 @@ public class XWalkView extends FrameLayout {
      * when the activyt for this view is resumed.
      */
     public void resumeTimers() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.resumeTimers();
     }
@@ -283,6 +394,7 @@ public class XWalkView extends FrameLayout {
      * Typically it should be called when the activity for this view is paused.
      */
     public void onHide() {
+        if (mContent == null) return;
         mExtensionManager.onPause();
         mContent.onPause();
     }
@@ -293,6 +405,7 @@ public class XWalkView extends FrameLayout {
      * Typically it should be called when the activity for this view is resumed.
      */
     public void onShow() {
+        if (mContent == null) return;
         mExtensionManager.onResume();
         mContent.onResume();
     }
@@ -313,6 +426,7 @@ public class XWalkView extends FrameLayout {
      * @param data passed from android.app.Activity.onActivityResult().
      */
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (mContent == null) return;
         mExtensionManager.onActivityResult(requestCode, resultCode, data);
         mContent.onActivityResult(requestCode, resultCode, data);
     }
@@ -324,6 +438,7 @@ public class XWalkView extends FrameLayout {
      * @param intent passed from android.app.Activity.onNewIntent().
      */
     public boolean onNewIntent(Intent intent) {
+        if (mContent == null) return false;
         return mContent.onNewIntent(intent);
     }
 
@@ -333,6 +448,7 @@ public class XWalkView extends FrameLayout {
      * @param outState the saved state for restoring.
      */
     public boolean saveState(Bundle outState) {
+        if (mContent == null) return false;
         mContent.saveState(outState);
         return true;
     }
@@ -343,6 +459,7 @@ public class XWalkView extends FrameLayout {
      * @return true if it can restore the state.
      */
     public boolean restoreState(Bundle inState) {
+        if (mContent == null) return false;
         if (mContent.restoreState(inState) != null) return true;
         return false;
     }
@@ -362,6 +479,7 @@ public class XWalkView extends FrameLayout {
      */
     // TODO(yongsheng): make it static?
     public String getXWalkVersion() {
+        if (mContent == null) return null;
         return mContent.getXWalkVersion();
     }
 
@@ -371,6 +489,7 @@ public class XWalkView extends FrameLayout {
      * @param client the XWalkUIClient defined by callers.
      */
     public void setUIClient(XWalkUIClient client) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setUIClient(client);
     }
@@ -381,17 +500,18 @@ public class XWalkView extends FrameLayout {
      * @param client the XWalkResourceClient defined by callers.
      */
     public void setResourceClient(XWalkResourceClient client) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setResourceClient(client);
     }
 
-    @Override
     /**
      * Inherit from android.view.View. This class needs to handle some keys like
      * 'BACK'.
      * @param keyCode passed from android.view.View.onKeyUp().
      * @param event passed from android.view.View.onKeyUp().
      */
+    @Override
     public boolean onKeyUp(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK) {
             // If there's navigation happens when app is fullscreen,
@@ -409,58 +529,82 @@ public class XWalkView extends FrameLayout {
     }
 
     // TODO(yongsheng): this is not public.
+    /**
+     * @hide
+     */
     public XWalkSettings getSettings() {
+        if (mContent == null) return null;
         checkThreadSafety();
         return mContent.getSettings();
     }
 
-    // TODO(yongsheng): remove this and related test cases?
+    /**
+     * This method is used by Cordova for hacking.
+     * TODO(yongsheng): remove this and related test cases?
+     *
+     * @hide
+     */
     public void setNetworkAvailable(boolean networkUp) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setNetworkAvailable(networkUp);
     }
 
-    // Enables remote debugging and returns the URL at which the dev tools server is listening
-    // for commands. The allowedUid argument can be used to specify the uid of the process that is
-    // permitted to connect.
-    // TODO(yongsheng): how to enable this in XWalkPreferences?
+    /**
+     * Enables remote debugging and returns the URL at which the dev tools server is listening
+     * for commands. The allowedUid argument can be used to specify the uid of the process that is
+     * permitted to connect.
+     * TODO(yongsheng): how to enable this in XWalkPreferences?
+     *
+     * @hide
+     */
     public String enableRemoteDebugging(int allowedUid) {
+        if (mContent == null) return null;
         checkThreadSafety();
         return mContent.enableRemoteDebugging(allowedUid);
     }
 
-    // It's used by presentation API.
-    // TODO(yongsheng): how to fix it?
+    /**
+     * It's used for Presentation API.
+     * @hide
+     */
     public int getContentID() {
+        if (mContent == null) return -1;
         return mContent.getRoutingID();
     }
 
     boolean canGoBack() {
+        if (mContent == null) return false;
         checkThreadSafety();
         return mContent.canGoBack();
     }
 
     void goBack() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.goBack();
     }
 
     boolean canGoForward() {
+        if (mContent == null) return false;
         checkThreadSafety();
         return mContent.canGoForward();
     }
 
     void goForward() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.goForward();
     }
 
     void clearHistory() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.clearHistory();
     }
 
     void destroy() {
+        if (mContent == null) return;
         mExtensionManager.onDestroy();
         mContent.destroy();
         disableRemoteDebugging();
@@ -473,6 +617,7 @@ public class XWalkView extends FrameLayout {
     }
 
     void disableRemoteDebugging() {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.disableRemoteDebugging();
     }
@@ -487,37 +632,63 @@ public class XWalkView extends FrameLayout {
         }
     }
 
+    boolean isOwnerActivityRunning() {
+        int status = ApplicationStatus.getStateForActivity(getActivity());
+        if (status == ActivityState.DESTROYED) return false;
+        return true;
+    }
+
     void navigateTo(int offset) {
+        if (mContent == null) return;
         mContent.navigateTo(offset);
     }
 
+    void setOverlayVideoMode(boolean enabled) {
+        mContent.setOverlayVideoMode(enabled);
+    }
+
     // Below methods are for test shell and instrumentation tests.
+    /**
+     * @hide
+     */
     public void setXWalkClient(XWalkClient client) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setXWalkClient(client);
     }
 
+    /**
+     * @hide
+     */
     public void setXWalkWebChromeClient(XWalkWebChromeClient client) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setXWalkWebChromeClient(client);
     }
 
-    public XWalkContent getXWalkViewContentForTest() {
-        checkThreadSafety();
-        return mContent;
-    }
-
+    /**
+     * @hide
+     */
     public void setDownloadListener(DownloadListener listener) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setDownloadListener(listener);
     }
 
+    /**
+     * @hide
+     */
     public void setNavigationHandler(XWalkNavigationHandler handler) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setNavigationHandler(handler);
     }
 
+    /**
+     * @hide
+     */
     public void setNotificationService(XWalkNotificationService service) {
+        if (mContent == null) return;
         checkThreadSafety();
         mContent.setNotificationService(service);
     }
index 1ed906b..98b69a6 100644 (file)
@@ -17,9 +17,9 @@ import android.content.res.Resources.NotFoundException;
 import android.os.Build;
 import android.util.Log;
 
-import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ApplicationStatusManager;
 import org.chromium.base.CommandLine;
+import org.chromium.base.JNINamespace;
 import org.chromium.base.PathUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.library_loader.LibraryLoader;
@@ -28,9 +28,12 @@ import org.chromium.content.browser.BrowserStartupController;
 import org.chromium.content.browser.DeviceUtils;
 import org.chromium.content.browser.ResourceExtractor;
 import org.chromium.content.browser.ResourceExtractor.ResourceIntercepter;
+import org.chromium.net.NetworkChangeNotifier;
 
+@JNINamespace("xwalk")
 class XWalkViewDelegate {
     private static boolean sInitialized = false;
+    private static boolean sRunningOnIA = true;
     private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "xwalkcore";
     private static final String[] MANDATORY_PAKS = {
             "xwalk.pak",
@@ -74,7 +77,7 @@ class XWalkViewDelegate {
         }
     }
 
-    public static void init(XWalkView xwalkView) {
+    public static void init(XWalkView xwalkView) throws UnsatisfiedLinkError {
         if (sInitialized) {
             return;
         }
@@ -83,6 +86,11 @@ class XWalkViewDelegate {
         // features such as location provider to listen to activity status.
         ApplicationStatusManager.init(xwalkView.getActivity().getApplication());
 
+        // Auto detect network connectivity state.
+        // setAutoDetectConnectivityState() need to be called before activity started.
+        NetworkChangeNotifier.init(xwalkView.getActivity());
+        NetworkChangeNotifier.setAutoDetectConnectivityState(true);
+
         // We will miss activity onCreate() status in ApplicationStatusManager,
         // informActivityStarted() will simulate these callbacks.
         ApplicationStatusManager.informActivityStarted(xwalkView.getActivity());
@@ -104,17 +112,17 @@ class XWalkViewDelegate {
         // 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())) {
-            try {
-                for (String library : MANDATORY_LIBRARIES) {
-                    System.load("/data/data/" + context.getPackageName() + "/lib/" + library);
-                }
-            } catch (UnsatisfiedLinkError e) {
-                throw new RuntimeException("Cannot initialize Crosswalk Core", e);
+            for (String library : MANDATORY_LIBRARIES) {
+                System.load("/data/data/" + context.getPackageName() + "/lib/" + library);
             }
         }
         loadLibrary(context);
         DeviceUtils.addDeviceSpecificUserAgentSwitch(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());
@@ -186,4 +194,14 @@ class XWalkViewDelegate {
             }
         });
     }
+
+    public static boolean isRunningOnIA() {
+        return sRunningOnIA;
+    }
+
+    private static native boolean nativeIsLibraryBuiltForIA();
+
+    static {
+        sRunningOnIA = Build.CPU_ABI.equalsIgnoreCase("x86");
+    }
 }
index d8ea367..6fabede 100644 (file)
@@ -34,6 +34,8 @@ import android.widget.FrameLayout;
  * It's an internal legacy class which is to handle kinds of ui related
  * callback functions. It only handles those which are not exposed to
  * external users compared to XWalkUIClient.
+ *
+ * @hide
  */
 public class XWalkWebChromeClient {
     private Context mContext;
@@ -43,8 +45,8 @@ public class XWalkWebChromeClient {
     private XWalkContentsClient mContentsClient = null;
     private long XWALK_MAX_QUOTA = 1024 * 1024 * 100;
 
-    public XWalkWebChromeClient(Context context, XWalkView view) {
-        mContext = context;
+    public XWalkWebChromeClient(XWalkView view) {
+        mContext = view.getContext();
         mXWalkView = view;
     }
 
index 69cc415..ea6812d 100644 (file)
@@ -26,6 +26,11 @@ abstract class XWalkWebContentsDelegate extends WebContentsDelegateAndroid {
     public abstract void rendererResponsive();
 
     @CalledByNative
+    public abstract boolean shouldOverrideRunFileChooser(
+            int processId, int renderId, int mode,
+            String acceptTypes, boolean capture);
+
+    @CalledByNative
     public void updatePreferredSize(int widthCss, int heightCss) {
     }
 
index 7edc165..3d7a12a 100644 (file)
@@ -56,4 +56,14 @@ class XWalkWebContentsDelegateAdapter extends XWalkWebContentsDelegate {
 
         return false;
     }
+
+    @Override
+    public boolean shouldOverrideRunFileChooser(int processId, int renderId, int mode,
+            String acceptTypes, boolean capture) {
+        if (mXWalkContentsClient != null) {
+            return mXWalkContentsClient.shouldOverrideRunFileChooser(processId, renderId, mode,
+                    acceptTypes, capture);
+        }
+        return false;
+    }
 }
index e0b6be0..4ca8e55 100644 (file)
@@ -9,9 +9,9 @@ import android.content.Context;
 import android.os.Bundle;
 import android.view.View;
 
-import org.xwalk.core.XWalkView;
-import org.xwalk.core.XWalkResourceClient;
+import org.xwalk.core.XWalkClient;
 import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
 
 /**
  * Represents the content to be presented on the secondary display.
@@ -25,23 +25,6 @@ public class XWalkPresentationContent {
     private Activity mActivity;
     private PresentationDelegate mDelegate;
 
-    private final XWalkResourceClient mXWalkResourceClient = new XWalkResourceClient() {
-        @Override
-        public void onLoadFinished(XWalkView view, String url) {
-            mPresentationId = mContentView.getContentID();
-            onContentLoaded();
-        }
-    };
-
-    private final XWalkUIClient mXWalkUIClient = new XWalkUIClient() {
-        @Override
-        public void onJavascriptCloseWindow(XWalkView view) {
-            // The content was closed already. Web need to invalidate the
-            // presentation id now.
-            mPresentationId = INVALID_PRESENTATION_ID;
-            onContentClosed();
-        }
-    };
 
     public XWalkPresentationContent(Context context, Activity activity, PresentationDelegate delegate) {
         mContext = context;
@@ -52,7 +35,25 @@ public class XWalkPresentationContent {
     public void load(final String url) {
         if (mContentView == null) {
             mContentView = new XWalkView(mContext, mActivity);
-            mContentView.setResourceClient(mXWalkResourceClient);
+            final XWalkClient xWalkClient = new XWalkClient(mContentView) {
+                @Override
+                public void onPageFinished(XWalkView view, String url) {
+                    mPresentationId = mContentView.getContentID();
+                    onContentLoaded();
+                }
+            };
+            mContentView.setXWalkClient(xWalkClient);
+
+            final XWalkUIClient xWalkUIClient = new XWalkUIClient(mContentView) {
+                @Override
+                public void onJavascriptCloseWindow(XWalkView view) {
+                    // The content was closed already. Web need to invalidate the
+                    // presentation id now.
+                    mPresentationId = INVALID_PRESENTATION_ID;
+                    onContentClosed();
+                }
+            };
+            mContentView.setUIClient(xWalkUIClient);
         }
         mContentView.load(url, null);
     }
diff --git a/src/xwalk/runtime/android/core/src/org/xwalk/core/package.html b/src/xwalk/runtime/android/core/src/org/xwalk/core/package.html
new file mode 100644 (file)
index 0000000..23cf75f
--- /dev/null
@@ -0,0 +1,7 @@
+<html>
+  <body>
+    <p>Provides an embedding API for browsing web and running web applications.
+    <p>For more information about building apps with Crosswalk embedding API, see the
+    <a href="https://crosswalk-project.org/">Crosswalk project</a>.
+  </body>
+</html>
index aa01c41..0c0778b 100644 (file)
       <message desc="Prompt for the http authentication login [CHAR-LIMIT=32]" name="IDS_HTTP_AUTH_LOG_IN">
         Log In
       </message>
+      <message desc="Title for the CPU architecture mismatch dialog [CHAR-LIMIT=50]" name="IDS_CPU_ARCH_MISMATCH_TITLE">
+        Mismatch of CPU architecture for Crosswalk
+      </message>
+      <message desc="Message for the CPU architecture mismatch dialog [CHAR-LIMIT=150]" name="IDS_CPU_ARCH_MISMATCH_MESSAGE">
+        Unfortunately this application was not created for %1$s based devices, please take a moment to notify the developer about it. Thanks.
+      </message>
+      <message desc="Label of the button for going to Google Play Store [CHAR-LIMIT=32]" name="IDS_GOTO_STORE_BUTTON_LABEL">
+        Go to Google Play Store
+      </message>
+      <message desc="Label of the button for reporting to developer [CHAR-LIMIT=32]" name="IDS_REPORT_FEEDBACK_BUTTON_LABEL">
+        Report to developer
+      </message>
     </messages>
   </release>
 
diff --git a/src/xwalk/runtime/android/core_library_empty/AndroidManifest.xml b/src/xwalk/runtime/android/core_library_empty/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..57353a8
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--  Copyright (c) 2013-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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.xwalk.core.library.empty">
+
+    <application android:name="android.app.Application"
+        android:label="XWalkCoreLibraryEmpty" android:hardwareAccelerated="true">
+    </application>
+
+  <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
+</manifest>
diff --git a/src/xwalk/runtime/android/core_library_empty/src/README.md b/src/xwalk/runtime/android/core_library_empty/src/README.md
new file mode 100644 (file)
index 0000000..3f8496e
--- /dev/null
@@ -0,0 +1,11 @@
+# Source folder for xwalk_core_library_empty_apk
+## Why it's empty
+The "xwalk_core_library_empty_apk" is an apk target which
+only depends on xwalk_core_java. The purpose of it is to
+get all the classes compiled from the code chromium generated
+for each apk.
+So there is no java src here.
+## Why put me here
+To make git keep the folder, the src directory is needed to
+build an apk.
+
index 3305ed9..54928e8 100644 (file)
@@ -32,6 +32,7 @@
   <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
index 787161c..06fa264 100644 (file)
@@ -38,7 +38,7 @@ import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.content.browser.TracingControllerAndroid;
 import org.xwalk.core.XWalkNavigationHistory;
 import org.xwalk.core.XWalkPreferences;
-import org.xwalk.core.XWalkResourceClientImpl;
+import org.xwalk.core.XWalkResourceClient;
 import org.xwalk.core.XWalkView;
 import org.xwalk.core.XWalkWebChromeClient;
 
@@ -101,6 +101,8 @@ public class XWalkViewShellActivity extends FragmentActivity
             getTracingController().unregisterReceiver(this);
         } catch (SecurityException e) {
             Log.w(TAG, "failed to unregister tracing receiver: " + e.getMessage());
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "failed to unregister tracing receiver: " + e.getMessage());
         }
     }
 
@@ -296,13 +298,13 @@ public class XWalkViewShellActivity extends FragmentActivity
         mReloadButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                if (mActiveView != null) mActiveView.reload();
+                if (mActiveView != null) mActiveView.reload(XWalkView.RELOAD_NORMAL);
             }
         });
     }
 
     private void initializeXWalkViewClients(XWalkView xwalkView) {
-        xwalkView.setResourceClient(new XWalkResourceClientImpl(this, xwalkView) {
+        xwalkView.setResourceClient(new XWalkResourceClient(xwalkView) {
             @Override
             public void onProgressChanged(XWalkView view, int newProgress) {
                 if (view != mActiveView) return;
@@ -318,7 +320,7 @@ public class XWalkViewShellActivity extends FragmentActivity
             }
         });
 
-        xwalkView.setXWalkWebChromeClient(new XWalkWebChromeClient(this, xwalkView) {
+        xwalkView.setXWalkWebChromeClient(new XWalkWebChromeClient(xwalkView) {
             @Override
             public void onReceivedTitle(XWalkView view, String title) {
                 mSectionsPagerAdapter.setPageTitle(view, title);
index 612b8a1..c6797f2 100644 (file)
@@ -42,6 +42,9 @@ class MixedContext extends ContextWrapper {
 
     @Override
     public Object getSystemService(String name) {
+        if (name.equals(Context.LAYOUT_INFLATER_SERVICE)) {
+            return super.getSystemService(name);
+        }
         return mActivityCtx.getSystemService(name);
     }
 }
index 34a4f42..a432f86 100644 (file)
@@ -43,15 +43,7 @@ class XWalkCoreProviderImpl implements XWalkRuntimeViewProvider {
 
     @Override
     public void loadAppFromManifest(String manifestUrl) {
-        XWalkManifestReader manifestReader = new XWalkManifestReader(mActivity);
-        String manifest = manifestReader.read(manifestUrl);
-        int position = manifestUrl.lastIndexOf("/");
-        if (position == -1) {
-            throw new RuntimeException("The URL of manifest file is invalid.");
-        }
-
-        String path = manifestUrl.substring(0, position + 1);
-        mXWalkView.loadAppFromManifest(path, manifest);
+        mXWalkView.loadAppFromManifest(manifestUrl, null);
     }
 
     @Override
@@ -121,9 +113,7 @@ class XWalkCoreProviderImpl implements XWalkRuntimeViewProvider {
 
     @Override
     public void loadDataForTest(String data, String mimeType, boolean isBase64Encoded) {
-        mXWalkView.getXWalkViewContentForTest().getContentViewCoreForTest(
-                ).loadUrl(LoadUrlParams.createLoadDataParams(
-                        data, mimeType, isBase64Encoded));
+        mXWalkView.load("", data);
     }
 
     @Override
diff --git a/src/xwalk/runtime/android/runtime/src/org/xwalk/runtime/XWalkManifestReader.java b/src/xwalk/runtime/android/runtime/src/org/xwalk/runtime/XWalkManifestReader.java
deleted file mode 100644 (file)
index 97536ee..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2013 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.runtime;
-
-import android.app.Activity;
-import android.content.res.AssetManager;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * This internal class parses manifest.json of current app.
- */
-class XWalkManifestReader {
-    private final static String TAG = "XWalkManifestReader";
-    private final static String ASSETS_FILE_PATH = "file:///android_asset/";
-    private final static String WWW_FOLDER = "www";
-    private final static String APP_SCHEME = "app";
-
-    private Activity mActivity;
-
-    public XWalkManifestReader(Activity activity) {
-        mActivity = activity;
-    }
-
-    public String read(String manifestPath) {
-        manifestPath = getAssetsPath(manifestPath);
-
-        String manifestString = null;
-        try {
-            manifestString = getAssetsFileContent(mActivity.getAssets(), manifestPath);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to read manifest.json", e);
-        }
-        return manifestString;
-    }
-
-    private String getAssetsFileContent(AssetManager assetManager, String fileName) throws IOException {
-        String result = "";
-        InputStream inputStream = null;
-        try {
-            inputStream = assetManager.open(fileName);
-            int size = inputStream.available();
-            byte[] buffer = new byte[size];
-            inputStream.read(buffer);
-            result = new String(buffer);
-        } finally {
-            if (inputStream != null) {
-                inputStream.close();
-            }
-        }
-        return result;
-    }
-
-    private String getAssetsPath(String path) {
-        if (path == null || path.isEmpty()) {
-            return null;
-        }
-
-        String assetsPath;
-        URI uri = null;
-        try {
-            uri = new URI(path);
-        } catch (URISyntaxException e) {
-            Log.e(TAG, "Invalid manifest URI: " + path, e);
-        }
-
-        if (uri.getScheme().equals(APP_SCHEME)) {
-            assetsPath = WWW_FOLDER + uri.getPath();
-        } else if (path.startsWith(ASSETS_FILE_PATH)) {
-            assetsPath = path.substring(ASSETS_FILE_PATH.length());
-        } else {
-            assetsPath = null;
-        }
-
-        return assetsPath;
-    }
-}
index a6352f5..8ede0af 100644 (file)
@@ -13,15 +13,14 @@ import java.lang.reflect.Method;
 
 import org.xwalk.core.XWalkClient;
 import org.xwalk.core.XWalkResourceClient;
-import org.xwalk.core.XWalkResourceClientImpl;
 import org.xwalk.core.XWalkWebChromeClient;
 import org.xwalk.core.XWalkView;
 
 class XWalkRuntimeTestHelper {
 
-    class TestXWalkResourceClient extends XWalkResourceClientImpl {
+    class TestXWalkResourceClient extends XWalkResourceClient {
         TestXWalkResourceClient(Context context, XWalkView view) {
-            super(context, view);
+            super(view);
         }
 
         @Override
@@ -44,7 +43,7 @@ class XWalkRuntimeTestHelper {
 
     class TestXWalkClient extends XWalkClient {
         TestXWalkClient(Context context, XWalkView view) {
-            super(context, view);
+            super(view);
         }
 
         @Override
@@ -78,7 +77,7 @@ class XWalkRuntimeTestHelper {
 
     class TestXWalkWebChromeClient extends XWalkWebChromeClient {
         TestXWalkWebChromeClient(Context context, XWalkView view) {
-            super(context, view);
+            super(view);
         }
 
         @Override
index 1148b92..65cce60 100644 (file)
@@ -32,6 +32,7 @@
   <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
diff --git a/src/xwalk/runtime/android/sample/AndroidManifest.xml b/src/xwalk/runtime/android/sample/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..afd955b
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.xwalk.core.sample"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application
+        android:name="android.app.Application"
+        android:hardwareAccelerated="true"
+        android:icon="@drawable/crosswalk"
+        android:label="CrosswalkSample" >
+        <activity
+            android:name="org.xwalk.core.sample.XWalkEmbeddingAPISample"
+            android:label="Crosswalk Sample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.XWalkViewWithLayoutActivity"
+            android:label="XWalkView UI Inflation"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.MultiXWalkViewActivity"
+            android:label="Multiple XWalkView Instances"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.LoadAppFromManifestActivity"
+            android:label="Manifest"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.ResourceAndUIClientsActivity"
+            android:label="XWalkResourceClient and XWalkUIClient"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.XWalkPreferencesActivity"
+            android:label="Preferences"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.XWalkNavigationActivity"
+            android:label="Page Navigation"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.PauseTimersActivity"
+            android:label="Pause/Resume JavaScript Timers"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.OnHideOnShowActivity"
+            android:label="Visibility Change"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/src/xwalk/runtime/android/sample/assets/index.html b/src/xwalk/runtime/android/sample/assets/index.html
new file mode 100644 (file)
index 0000000..5c49c6b
--- /dev/null
@@ -0,0 +1,6 @@
+<html>
+    <body>
+        Hello World.
+        <script>alert('Hello World!')</script>
+    </body>
+</html>
diff --git a/src/xwalk/runtime/android/sample/assets/manifest.json b/src/xwalk/runtime/android/sample/assets/manifest.json
new file mode 100644 (file)
index 0000000..24bc99c
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "name": "ManifestTest",
+  "start_url": "index.html",
+  "app": {
+    "launch": {
+      "local_path": "index.html"
+    }
+  },
+  "description": "Manifest test",
+  "version": "1.0.0"
+}
diff --git a/src/xwalk/runtime/android/sample/assets/pause_timers.html b/src/xwalk/runtime/android/sample/assets/pause_timers.html
new file mode 100644 (file)
index 0000000..60f92f0
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<p>A script on this page starts this clock:</p>
+<p id="demo"></p>
+
+<script>
+  var myVar = setInterval(function(){ myTimer(); }, 1000);
+
+  function myTimer()
+  {
+    var d = new Date();
+    var t = d.toLocaleTimeString();
+    document.getElementById("demo").innerHTML = t;
+  }
+</script>
+
+</body>
+</html>
diff --git a/src/xwalk/runtime/android/sample/res/drawable-hdpi/crosswalk.png b/src/xwalk/runtime/android/sample/res/drawable-hdpi/crosswalk.png
new file mode 100644 (file)
index 0000000..5989755
Binary files /dev/null and b/src/xwalk/runtime/android/sample/res/drawable-hdpi/crosswalk.png differ
diff --git a/src/xwalk/runtime/android/sample/res/drawable-ldpi/crosswalk.png b/src/xwalk/runtime/android/sample/res/drawable-ldpi/crosswalk.png
new file mode 100644 (file)
index 0000000..e87864a
Binary files /dev/null and b/src/xwalk/runtime/android/sample/res/drawable-ldpi/crosswalk.png differ
diff --git a/src/xwalk/runtime/android/sample/res/drawable-mdpi/crosswalk.png b/src/xwalk/runtime/android/sample/res/drawable-mdpi/crosswalk.png
new file mode 100644 (file)
index 0000000..fc19a3e
Binary files /dev/null and b/src/xwalk/runtime/android/sample/res/drawable-mdpi/crosswalk.png differ
diff --git a/src/xwalk/runtime/android/sample/res/drawable-xhdpi/crosswalk.png b/src/xwalk/runtime/android/sample/res/drawable-xhdpi/crosswalk.png
new file mode 100644 (file)
index 0000000..b69b4e8
Binary files /dev/null and b/src/xwalk/runtime/android/sample/res/drawable-xhdpi/crosswalk.png differ
diff --git a/src/xwalk/runtime/android/sample/res/layout/container.xml b/src/xwalk/runtime/android/sample/res/layout/container.xml
new file mode 100644 (file)
index 0000000..40058d0
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="2"
+    android:orientation="vertical" >
+
+</LinearLayout>
diff --git a/src/xwalk/runtime/android/sample/res/layout/navigation_layout.xml b/src/xwalk/runtime/android/sample/res/layout/navigation_layout.xml
new file mode 100644 (file)
index 0000000..27c55f0
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <ImageButton
+            android:id="@+id/prev"
+            android:layout_width="38dp"
+            android:layout_height="38dp"
+            android:scaleType="center"
+            android:src="@android:drawable/ic_media_previous" />
+
+        <ImageButton
+            android:id="@+id/next"
+            android:layout_width="38dp"
+            android:layout_height="38dp"
+            android:scaleType="center"
+            android:src="@android:drawable/ic_media_next" />
+    </LinearLayout>
+
+    <org.xwalk.core.XWalkView
+        android:id="@+id/xwalkview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+    </org.xwalk.core.XWalkView>
+
+</LinearLayout>
diff --git a/src/xwalk/runtime/android/sample/res/layout/pause_timers_layout.xml b/src/xwalk/runtime/android/sample/res/layout/pause_timers_layout.xml
new file mode 100644 (file)
index 0000000..da9d56d
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <ImageButton
+            android:id="@+id/pause"
+            android:layout_width="38dp"
+            android:layout_height="38dp"
+            android:scaleType="center"
+            android:src="@android:drawable/ic_media_pause" />
+    </LinearLayout>
+
+    <org.xwalk.core.XWalkView
+        android:id="@+id/xwalkview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+    </org.xwalk.core.XWalkView>
+
+</LinearLayout>
diff --git a/src/xwalk/runtime/android/sample/res/layout/xwview_layout.xml b/src/xwalk/runtime/android/sample/res/layout/xwview_layout.xml
new file mode 100644 (file)
index 0000000..810013e
--- /dev/null
@@ -0,0 +1,13 @@
+<!--
+ 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.
+-->
+
+<org.xwalk.core.XWalkView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/xwalkview"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+</org.xwalk.core.XWalkView>
diff --git a/src/xwalk/runtime/android/sample/res/values/strings.xml b/src/xwalk/runtime/android/sample/res/values/strings.xml
new file mode 100644 (file)
index 0000000..cf639b5
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2013-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.
+-->
+
+<resources>
+    
+</resources>
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/LoadAppFromManifestActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/LoadAppFromManifestActivity.java
new file mode 100644 (file)
index 0000000..8effcd9
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.sample;
+
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class LoadAppFromManifestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.xwview_layout);
+        XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
+
+        // The manifest definition, please refer to the link:
+        // https://crosswalk-project.org/#wiki/Crosswalk-manifest 
+        xwalkView.loadAppFromManifest("file:///android_asset/manifest.json", null);
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/MultiXWalkViewActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/MultiXWalkViewActivity.java
new file mode 100644 (file)
index 0000000..09b4545
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.sample;
+
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+
+public class MultiXWalkViewActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.container);
+        LinearLayout parent = (LinearLayout) findViewById(R.id.container);
+
+        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.MATCH_PARENT,
+                LinearLayout.LayoutParams.MATCH_PARENT);
+        params.weight = 1;
+
+        XWalkView view1 = new XWalkView(this, this);
+        parent.addView(view1, params);
+
+        XWalkView view2 = new XWalkView(this, this);
+        parent.addView(view2, params);
+
+        view1.load("http://www.intel.com", null);
+        view2.load("http://www.baidu.com", null);
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnHideOnShowActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnHideOnShowActivity.java
new file mode 100644 (file)
index 0000000..99f503f
--- /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.sample;
+
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class OnHideOnShowActivity extends Activity {
+
+    private XWalkView mXWalkView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.xwview_layout);
+        mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+
+        mXWalkView.load("http://www.w3.org/2010/05/video/mediaevents.html", null);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        // It will pause the video, when the app in background.
+        mXWalkView.onHide();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        // Need to call onShow() when onHide() was called.
+        mXWalkView.onShow();
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/PauseTimersActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/PauseTimersActivity.java
new file mode 100644 (file)
index 0000000..d93bb41
--- /dev/null
@@ -0,0 +1,49 @@
+// 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.sample;
+
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageButton;
+
+public class PauseTimersActivity extends Activity {
+
+    private ImageButton mButton;
+    private boolean isPaused;
+    XWalkView mXWalkView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pause_timers_layout);
+        mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+
+        isPaused = false;
+        mButton = (ImageButton) findViewById(R.id.pause);
+        mButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mXWalkView != null) {
+                    if (!isPaused) {
+                        // Pause JS timer
+                        mXWalkView.pauseTimers();
+                        isPaused = true;
+                        mButton.setImageResource(android.R.drawable.ic_media_play);
+                    } else {
+                        // Resume JS timer
+                        mXWalkView.resumeTimers();
+                        isPaused = false;
+                        mButton.setImageResource(android.R.drawable.ic_media_pause);
+                    }
+                }
+            }
+        });
+        mXWalkView.load("file:///android_asset/pause_timers.html", null);
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/ResourceAndUIClientsActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/ResourceAndUIClientsActivity.java
new file mode 100644 (file)
index 0000000..3a443c0
--- /dev/null
@@ -0,0 +1,104 @@
+// 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.sample;
+
+import org.xwalk.core.XWalkJavascriptResult;
+import org.xwalk.core.XWalkResourceClient;
+import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.webkit.ValueCallback;
+import android.webkit.WebResourceResponse;
+
+public class ResourceAndUIClientsActivity extends Activity {
+
+    private static final String TAG = ResourceAndUIClientsActivity.class.getName();
+
+    class ResourceCLient extends XWalkResourceClient {
+
+        public ResourceCLient(XWalkView xwalkView) {
+            super(xwalkView);
+        }
+
+        public void onLoadStarted(XWalkView view, String url) {
+            super.onLoadStarted(view, url);
+            Log.d(TAG, "Load Started:" + url);
+        }
+
+        public void onLoadFinished(XWalkView view, String url) {
+            super.onLoadFinished(view, url);
+            Log.d(TAG, "Load Finished:" + url);
+        }
+
+        public void onProgressChanged(XWalkView view, int progressInPercent) {
+            super.onProgressChanged(view, progressInPercent);
+            Log.d(TAG, "Loading Progress:" + progressInPercent);
+        }
+
+        public WebResourceResponse shouldInterceptLoadRequest(XWalkView view, String url) {
+            Log.d(TAG, "Intercept load request");
+            return super.shouldInterceptLoadRequest(view, url);
+        }
+
+        public void onReceivedLoadError(XWalkView view, int errorCode, String description,
+                String failingUrl) {
+            Log.d(TAG, "Load Failed:" + description);
+            super.onReceivedLoadError(view, errorCode, description, failingUrl);
+        }
+    }
+
+    class UIClient extends XWalkUIClient {
+
+        public UIClient(XWalkView xwalkView) {
+            super(xwalkView);
+        }
+
+        public void onJavascriptCloseWindow(XWalkView view) {
+            super.onJavascriptCloseWindow(view);
+            Log.d(TAG, "Window closed.");
+        }
+
+        public boolean onJavascriptModalDialog(XWalkView view, JavascriptMessageType type,
+                String url,
+                String message, String defaultValue, XWalkJavascriptResult result) {
+            Log.d(TAG, "Show JS dialog.");
+            return super.onJavascriptModalDialog(view, type, url, message, defaultValue, result);
+        }
+
+        public void onFullscreenToggled(XWalkView view, boolean enterFullscreen) {
+            super.onFullscreenToggled(view, enterFullscreen);
+            if (enterFullscreen) {
+                Log.d(TAG, "Entered fullscreen.");
+            } else {
+                Log.d(TAG, "Exited fullscreen.");
+            }
+        }
+
+        public void openFileChooser(XWalkView view, ValueCallback<Uri> uploadFile,
+                String acceptType, String capture) {
+            super.openFileChooser(view, uploadFile, acceptType, capture);
+            Log.d(TAG, "Opened file chooser.");
+        }
+
+        public void onScaleChanged(XWalkView view, float oldScale, float newScale) {
+            super.onScaleChanged(view, oldScale, newScale);
+            Log.d(TAG, "Scale changed.");
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.xwview_layout);
+        XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
+        xwalkView.setResourceClient(new ResourceCLient(xwalkView));
+        xwalkView.setUIClient(new UIClient(xwalkView));
+        xwalkView.load("http://www.baidu.com", null);
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkEmbeddingAPISample.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkEmbeddingAPISample.java
new file mode 100644 (file)
index 0000000..1e0dd05
--- /dev/null
@@ -0,0 +1,114 @@
+// 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.sample;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+public class XWalkEmbeddingAPISample extends ListActivity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setListAdapter(new SampleAdapter());
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+    }
+
+    @Override
+    protected void onListItemClick(ListView lv, View v, int pos, long id) {
+        SampleInfo info = (SampleInfo) getListAdapter().getItem(pos);
+        startActivity(info.intent);
+    }
+
+    static class SampleInfo {
+        String name;
+        Intent intent;
+
+        SampleInfo(String name, Intent intent) {
+            this.name = name;
+            this.intent = intent;
+        }
+    }
+
+    class SampleAdapter extends BaseAdapter {
+        private ArrayList<SampleInfo> mItems;
+
+        public SampleAdapter() {
+            Intent intent = new Intent(Intent.ACTION_MAIN, null);
+            intent.setPackage(getPackageName());
+            intent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
+
+            PackageManager pm = getPackageManager();
+            List<ResolveInfo> infos = pm.queryIntentActivities(intent, 0);
+
+            mItems = new ArrayList<SampleInfo>();
+
+            final int count = infos.size();
+            for (int i = 0; i < count; i++) {
+                final ResolveInfo info = infos.get(i);
+                final CharSequence labelSeq = info.loadLabel(pm);
+                String label = labelSeq != null ? labelSeq.toString() : info.activityInfo.name;
+
+                Intent target = new Intent();
+                target.setClassName(info.activityInfo.applicationInfo.packageName,
+                        info.activityInfo.name);
+                SampleInfo sample = new SampleInfo(label, target);
+                mItems.add(sample);
+            }
+        }
+
+        @Override
+        public int getCount() {
+            return mItems.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = getLayoutInflater().inflate(android.R.layout.simple_list_item_1,
+                        parent, false);
+            }
+            TextView tv = (TextView) convertView.findViewById(android.R.id.text1);
+            SampleInfo info = mItems.get(position);
+            tv.setText(info.name);
+            return convertView;
+        }
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkNavigationActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkNavigationActivity.java
new file mode 100644 (file)
index 0000000..a4d37dc
--- /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.sample;
+
+import org.xwalk.core.XWalkView;
+import org.xwalk.core.XWalkNavigationHistory;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageButton;
+
+public class XWalkNavigationActivity extends Activity {
+
+    private ImageButton mNextButton;
+    private ImageButton mPrevButton;
+    private XWalkView mXWalkView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.navigation_layout);
+        mPrevButton = (ImageButton) findViewById(R.id.prev);
+        mNextButton = (ImageButton) findViewById(R.id.next);
+        mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+
+        mPrevButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // Go backward
+                if (mXWalkView != null &&
+                        mXWalkView.getNavigationHistory().canGoBack()) {
+                    mXWalkView.getNavigationHistory().navigate(
+                            XWalkNavigationHistory.Direction.BACKWARD, 1);
+                }
+            }
+        });
+
+        mNextButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // Go forward
+                if (mXWalkView != null &&
+                        mXWalkView.getNavigationHistory().canGoForward()) {
+                    mXWalkView.getNavigationHistory().navigate(
+                            XWalkNavigationHistory.Direction.FORWARD, 1);
+                }
+            }
+        });
+
+        mXWalkView.load("http://www.baidu.com/", null);
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkPreferencesActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkPreferencesActivity.java
new file mode 100644 (file)
index 0000000..96da1dd
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.sample;
+
+import org.xwalk.core.XWalkPreferences;
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class XWalkPreferencesActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.xwview_layout);
+        XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
+
+        // Enable remote debugging.
+        // You can debug the web content via PC chrome.
+        XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);
+
+        xwalkView.load("http://www.baidu.com/", null);
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkViewWithLayoutActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/XWalkViewWithLayoutActivity.java
new file mode 100644 (file)
index 0000000..e9739d8
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.sample;
+
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class XWalkViewWithLayoutActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.xwview_layout);
+        XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
+        xwalkView.load("http://www.baidu.com/", null);
+    }
+}
index 16f6c06..9c9849a 100644 (file)
@@ -19,6 +19,7 @@
 #include "xwalk/runtime/browser/android/xwalk_dev_tools_server.h"
 #include "xwalk/runtime/browser/android/xwalk_http_auth_handler.h"
 #include "xwalk/runtime/browser/android/xwalk_settings.h"
+#include "xwalk/runtime/browser/android/xwalk_view_delegate.h"
 #include "xwalk/runtime/browser/android/xwalk_web_contents_delegate.h"
 
 namespace xwalk {
@@ -41,6 +42,7 @@ static base::android::RegistrationMethod kXWalkRegisteredMethods[] = {
   { "XWalkExtensionAndroid", extensions::RegisterXWalkExtensionAndroid },
   { "XWalkHttpAuthHandler", RegisterXWalkHttpAuthHandler },
   { "XWalkSettings", RegisterXWalkSettings },
+  { "XWalkViewDelegate", RegisterXWalkViewDelegate },
   { "XWalkWebContentsDelegate", RegisterXWalkWebContentsDelegate },
 };
 
index 96a1ab2..7b88f02 100644 (file)
@@ -19,7 +19,8 @@ namespace xwalk {
 
 XWalkRenderViewHostExt::XWalkRenderViewHostExt(content::WebContents* contents)
     : content::WebContentsObserver(contents),
-      has_new_hit_test_data_(false) {
+      has_new_hit_test_data_(false),
+      is_render_view_created_(false) {
 }
 
 XWalkRenderViewHostExt::~XWalkRenderViewHostExt() {}
@@ -80,6 +81,15 @@ void XWalkRenderViewHostExt::SetInitialPageScale(double page_scale_factor) {
                                          page_scale_factor));
 }
 
+void XWalkRenderViewHostExt::RenderViewCreated(
+    content::RenderViewHost* render_view_host) {
+  if (!pending_base_url_.empty()) {
+    Send(new XWalkViewMsg_SetOriginAccessWhitelist(
+        pending_base_url_, pending_match_patterns_));
+  }
+  is_render_view_created_ = true;
+}
+
 void XWalkRenderViewHostExt::SetJsOnlineProperty(bool network_up) {
   Send(new XWalkViewMsg_SetJsOnlineProperty(network_up));
 }
@@ -136,4 +146,17 @@ void XWalkRenderViewHostExt::OnUpdateHitTestData(
   has_new_hit_test_data_ = true;
 }
 
+void XWalkRenderViewHostExt::SetOriginAccessWhitelist(
+    const std::string& base_url,
+    const std::string& match_patterns) {
+  DCHECK(CalledOnValidThread());
+  pending_base_url_ = base_url;
+  pending_match_patterns_ = match_patterns;
+
+  if (is_render_view_created_) {
+    Send(new XWalkViewMsg_SetOriginAccessWhitelist(
+        pending_base_url_, pending_match_patterns_));
+  }
+}
+
 }  // namespace xwalk
index a521c7a..a4b5285 100644 (file)
@@ -6,6 +6,7 @@
 #define XWALK_RUNTIME_BROWSER_ANDROID_RENDERER_HOST_XWALK_RENDER_VIEW_HOST_EXT_H_
 
 #include <map>
+#include <string>
 
 #include "base/callback_forward.h"
 #include "base/threading/non_thread_safe.h"
@@ -62,8 +63,14 @@ class XWalkRenderViewHostExt : public content::WebContentsObserver,
   void SetInitialPageScale(double page_scale_factor);
   void SetJsOnlineProperty(bool network_up);
 
+  // Sets the white list for Cross-Origin access.
+  void SetOriginAccessWhitelist(const std::string& base_url,
+                                const std::string& permissions);
+
  private:
   // content::WebContentsObserver implementation.
+  virtual void RenderViewCreated(
+      content::RenderViewHost* render_view_host) OVERRIDE;
   virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
   virtual void DidNavigateAnyFrame(
       const content::LoadCommittedDetails& details,
@@ -85,6 +92,10 @@ class XWalkRenderViewHostExt : public content::WebContentsObserver,
 
   bool has_new_hit_test_data_;
 
+  std::string pending_base_url_;
+  std::string pending_match_patterns_;
+  bool is_render_view_created_;
+
   DISALLOW_COPY_AND_ASSIGN(XWalkRenderViewHostExt);
 };
 
index a4893f7..3374407 100644 (file)
@@ -14,6 +14,7 @@
 #include "base/android/jni_string.h"
 #include "base/base_paths_android.h"
 #include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
 #include "base/path_service.h"
 #include "base/pickle.h"
 #include "content/public/browser/browser_context.h"
@@ -46,6 +47,8 @@ using content::WebContents;
 using navigation_interception::InterceptNavigationDelegate;
 using xwalk::application_manifest_keys::kDisplay;
 
+namespace keys = xwalk::application_manifest_keys;
+
 namespace xwalk {
 
 namespace {
@@ -103,7 +106,7 @@ XWalkContent* XWalkContent::FromWebContents(
   return XWalkContentUserData::GetContents(web_contents);
 }
 
-jint XWalkContent::GetWebContents(
+jlong XWalkContent::GetWebContents(
     JNIEnv* env, jobject obj, jobject io_thread_client,
     jobject intercept_navigation_delegate) {
   if (!web_contents_) {
@@ -113,7 +116,7 @@ jint XWalkContent::GetWebContents(
     render_view_host_ext_.reset(
         new XWalkRenderViewHostExt(web_contents_.get()));
   }
-  return reinterpret_cast<jint>(web_contents_.get());
+  return reinterpret_cast<intptr_t>(web_contents_.get());
 }
 
 content::WebContents* XWalkContent::CreateWebContents(
@@ -212,8 +215,7 @@ jboolean XWalkContent::SetManifest(JNIEnv* env,
       manifest_dictionary_ptr.Pass());
 
   std::string url;
-  if (manifest.GetString(
-          xwalk::application_manifest_keys::kLaunchLocalPathKey, &url)) {
+  if (manifest.GetString(keys::kLaunchLocalPathKey, &url)) {
     // According to original proposal for "app:launch:local_path", the "http"
     // and "https" schemes are supported. So |url| should do nothing when it
     // already has "http" or "https" scheme.
@@ -221,13 +223,19 @@ jboolean XWalkContent::SetManifest(JNIEnv* env,
     if (scheme != content::kHttpScheme && scheme != content::kHttpsScheme)
       url = path_str + url;
   } else {
-    manifest.GetString(
-        xwalk::application_manifest_keys::kLaunchWebURLKey, &url);
+    manifest.GetString(keys::kLaunchWebURLKey, &url);
+  }
+
+  std::string match_patterns;
+  const base::ListValue* xwalk_hosts = NULL;
+  if (manifest.GetList(
+          xwalk::application_manifest_keys::kXWalkHostsKey, &xwalk_hosts)) {
+      base::JSONWriter::Write(xwalk_hosts, &match_patterns);
   }
+  render_view_host_ext_->SetOriginAccessWhitelist(url, match_patterns);
 
   std::string csp;
-  manifest.GetString(
-      xwalk::application_manifest_keys::kCSPKey, &csp);
+  manifest.GetString(keys::kCSPKey, &csp);
   RuntimeContext* runtime_context =
       XWalkRunner::GetInstance()->runtime_context();
   CHECK(runtime_context);
@@ -248,17 +256,51 @@ jboolean XWalkContent::SetManifest(JNIEnv* env,
   }
 
   // Check whether need to display launch screen. (Read from manifest.json)
-  if (manifest.HasPath(
-          xwalk::application_manifest_keys::kLaunchScreen)) {
+  if (manifest.HasPath(keys::kLaunchScreen)) {
     std::string ready_when;
-    // Get the value of 'ready_when' from manifest.json and callback
-    // to Java side.
-    manifest.GetString(
-        xwalk::application_manifest_keys::kLaunchScreenReadyWhen, &ready_when);
+    // Get the value of 'ready_when' from manifest.json
+    manifest.GetString(keys::kLaunchScreenReadyWhen, &ready_when);
     ScopedJavaLocalRef<jstring> ready_when_buffer =
         base::android::ConvertUTF8ToJavaString(env, ready_when);
+
+    // Get the value of 'image_border'
+    // 1. When 'launch_screen.[orientation]' was defined, but no 'image_border'
+    //    The value of 'image_border' will be set as 'empty'.
+    // 2. Otherwise, there is no 'launch_screen.[orientation]' defined,
+    //    The value of 'image_border' will be empty.
+    const char empty[] = "empty";
+    std::string image_border_default;
+    manifest.GetString(keys::kLaunchScreenImageBorderDefault,
+                       &image_border_default);
+    if (image_border_default.empty() && manifest.HasPath(
+        keys::kLaunchScreenDefault)) {
+      image_border_default = empty;
+    }
+
+    std::string image_border_landscape;
+    manifest.GetString(keys::kLaunchScreenImageBorderLandscape,
+                       &image_border_landscape);
+    if (image_border_landscape.empty() && manifest.HasPath(
+        keys::kLaunchScreenLandscape)) {
+      image_border_landscape = empty;
+    }
+
+    std::string image_border_portrait;
+    manifest.GetString(keys::kLaunchScreenImageBorderPortrait,
+                       &image_border_portrait);
+    if (image_border_portrait.empty() && manifest.HasPath(
+        keys::kLaunchScreenPortrait)) {
+      image_border_portrait = empty;
+    }
+
+    std::string image_border = image_border_default + ';' +
+        image_border_landscape  + ';' + image_border_portrait;
+    ScopedJavaLocalRef<jstring> image_border_buffer =
+        base::android::ConvertUTF8ToJavaString(env, image_border);
+
     Java_XWalkContent_onGetUrlAndLaunchScreenFromManifest(
-        env, obj, url_buffer.obj(), ready_when_buffer.obj());
+        env, obj, url_buffer.obj(), ready_when_buffer.obj(),
+        image_border_buffer.obj());
   } else {
     // No need to display launch screen, load the url directly.
     Java_XWalkContent_onGetUrlFromManifest(env, obj, url_buffer.obj());
@@ -299,11 +341,11 @@ jboolean XWalkContent::SetState(JNIEnv* env, jobject obj, jbyteArray state) {
   return RestoreFromPickle(&iterator, web_contents_.get());
 }
 
-static jint Init(JNIEnv* env, jobject obj, jobject web_contents_delegate,
+static jlong Init(JNIEnv* env, jobject obj, jobject web_contents_delegate,
     jobject contents_client_bridge) {
   XWalkContent* xwalk_core_content =
     new XWalkContent(env, obj, web_contents_delegate, contents_client_bridge);
-  return reinterpret_cast<jint>(xwalk_core_content);
+  return reinterpret_cast<intptr_t>(xwalk_core_content);
 }
 
 bool RegisterXWalkContent(JNIEnv* env) {
@@ -342,7 +384,7 @@ void ShowGeolocationPromptHelper(const JavaObjectWeakGlobalRef& java_ref,
 
 void XWalkContent::ShowGeolocationPrompt(
     const GURL& requesting_frame,
-    const base::Callback<void(bool)>& callback) {
+    const base::Callback<void(bool)>& callback) { // NOLINT
   GURL origin = requesting_frame.GetOrigin();
   bool show_prompt = pending_geolocation_prompts_.empty();
   pending_geolocation_prompts_.push_back(OriginCallback(origin, callback));
index c12cd14..ca6b799 100644 (file)
@@ -35,7 +35,7 @@ class XWalkContent {
   static XWalkContent* FromID(int render_process_id, int render_view_id);
   static XWalkContent* FromWebContents(content::WebContents* web_contents);
 
-  jint GetWebContents(JNIEnv* env, jobject obj, jobject io_thread_client,
+  jlong GetWebContents(JNIEnv* env, jobject obj, jobject io_thread_client,
                       jobject delegate);
   void ClearCache(JNIEnv* env, jobject obj, jboolean include_disk_files);
   ScopedJavaLocalRef<jstring> DevToolsAgentId(JNIEnv* env, jobject obj);
@@ -62,7 +62,7 @@ class XWalkContent {
 
   // Geolocation API support
   void ShowGeolocationPrompt(const GURL& origin,
-                             const base::Callback<void(bool)>& callback);
+                             const base::Callback<void(bool)>& callback); // NOLINT
   void HideGeolocationPrompt(const GURL& origin);
   void InvokeGeolocationCallback(JNIEnv* env,
                                  jobject obj,
@@ -82,7 +82,7 @@ class XWalkContent {
   // GURL is supplied by the content layer as requesting frame.
   // Callback is supplied by the content layer, and is invoked with the result
   // from the permission prompt.
-  typedef std::pair<const GURL, const base::Callback<void(bool)> > \
+  typedef std::pair<const GURL, const base::Callback<void(bool)> >  /* NOLINT */ \
           OriginCallback;
   // The first element in the list is always the currently pending request.
   std::list<OriginCallback> pending_geolocation_prompts_;
index b0779d6..0450dad 100644 (file)
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/file_chooser_params.h"
 #include "content/public/common/show_desktop_notification_params.h"
 #include "jni/XWalkContentsClientBridge_jni.h"
 #include "net/cert/x509_certificate.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "url/gurl.h"
 #include "ui/gfx/android/java_bitmap.h"
+#include "ui/shell_dialogs/selected_file_info.h"
 
 using base::android::AttachCurrentThread;
 using base::android::ConvertJavaStringToUTF16;
@@ -27,6 +29,7 @@ using base::android::ConvertUTF16ToJavaString;
 using base::android::JavaRef;
 using base::android::ScopedJavaLocalRef;
 using content::BrowserThread;
+using content::FileChooserParams;
 using content::RenderViewHost;
 using content::WebContents;
 
@@ -51,7 +54,7 @@ XWalkContentsClientBridge::XWalkContentsClientBridge(JNIEnv* env, jobject obj)
     : java_ref_(env, obj) {
   DCHECK(obj);
   Java_XWalkContentsClientBridge_setNativeContentsClientBridge(
-      env, obj, reinterpret_cast<jint>(this));
+      env, obj, reinterpret_cast<intptr_t>(this));
 }
 
 XWalkContentsClientBridge::~XWalkContentsClientBridge() {
@@ -70,7 +73,7 @@ void XWalkContentsClientBridge::AllowCertificateError(
     int cert_error,
     net::X509Certificate* cert,
     const GURL& request_url,
-    const base::Callback<void(bool)>& callback,
+    const base::Callback<void(bool)>& callback, // NOLINT
     bool* cancel_request) {
 
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -332,7 +335,7 @@ void XWalkContentsClientBridge::CancelJsResult(JNIEnv*, jobject, int id) {
 }
 
 void XWalkContentsClientBridge::ExitFullscreen(
-    JNIEnv*, jobject, jint j_web_contents) {
+    JNIEnv*, jobject, jlong j_web_contents) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   WebContents* web_contents = reinterpret_cast<WebContents*>(j_web_contents);
   if (web_contents) {
@@ -387,6 +390,43 @@ void XWalkContentsClientBridge::NotificationClosed(
   rvh->DesktopNotificationPostClose(id, by_user);
 }
 
+void XWalkContentsClientBridge::OnFilesSelected(
+    JNIEnv* env, jobject, int process_id, int render_id,
+    int mode, jstring filepath, jstring display_name) {
+  content::RenderViewHost* rvh =
+      content::RenderViewHost::FromID(process_id, render_id);
+  if (!rvh)
+    return;
+
+  std::string path = base::android::ConvertJavaStringToUTF8(env, filepath);
+  std::string file_name =
+      base::android::ConvertJavaStringToUTF8(env, display_name);
+  base::FilePath file_path = base::FilePath(path);
+  ui::SelectedFileInfo file_info;
+  file_info.file_path = file_path;
+  file_info.local_path = file_path;
+  if (!file_name.empty())
+    file_info.display_name = file_name;
+  std::vector<ui::SelectedFileInfo> files;
+  files.push_back(file_info);
+
+  rvh->FilesSelectedInChooser(
+      files, static_cast<content::FileChooserParams::Mode>(mode));
+}
+
+void XWalkContentsClientBridge::OnFilesNotSelected(
+    JNIEnv* env, jobject, int process_id, int render_id, int mode) {
+  content::RenderViewHost* rvh =
+      content::RenderViewHost::FromID(process_id, render_id);
+  if (!rvh)
+    return;
+
+  std::vector<ui::SelectedFileInfo> files;
+
+  rvh->FilesSelectedInChooser(
+      files, static_cast<content::FileChooserParams::Mode>(mode));
+}
+
 bool RegisterXWalkContentsClientBridge(JNIEnv* env) {
   return RegisterNativesImpl(env) >= 0;
 }
index 4be301a..022a993 100644 (file)
@@ -45,7 +45,7 @@ class XWalkContentsClientBridge : public XWalkContentsClientBridgeBase {
   virtual void AllowCertificateError(int cert_error,
                                      net::X509Certificate* cert,
                                      const GURL& request_url,
-                                     const base::Callback<void(bool)>& callback,
+                                     const base::Callback<void(bool)>& callback, // NOLINT
                                      bool* cancel_request) OVERRIDE;
 
   virtual void RunJavaScriptDialog(
@@ -91,7 +91,7 @@ class XWalkContentsClientBridge : public XWalkContentsClientBridgeBase {
   void ProceedSslError(JNIEnv* env, jobject obj, jboolean proceed, jint id);
   void ConfirmJsResult(JNIEnv*, jobject, int id, jstring prompt);
   void CancelJsResult(JNIEnv*, jobject, int id);
-  void ExitFullscreen(JNIEnv*, jobject, jint web_contents);
+  void ExitFullscreen(JNIEnv*, jobject, jlong web_contents);
   void NotificationDisplayed(
       JNIEnv*, jobject, int id, int process_id, int route_id);
   void NotificationError(
@@ -100,11 +100,16 @@ class XWalkContentsClientBridge : public XWalkContentsClientBridgeBase {
       JNIEnv*, jobject, int id, int process_id, int route_id);
   void NotificationClosed(
       JNIEnv*, jobject, int id, bool by_user, int process_id, int route_id);
+  void OnFilesSelected(
+      JNIEnv*, jobject, int process_id, int render_id,
+      int mode, jstring filepath, jstring display_name);
+  void OnFilesNotSelected(
+      JNIEnv*, jobject, int process_id, int render_id, int mode);
 
  private:
   JavaObjectWeakGlobalRef java_ref_;
 
-  typedef const base::Callback<void(bool)> CertErrorCallback;
+  typedef const base::Callback<void(bool)> CertErrorCallback; // NOLINT
   IDMap<CertErrorCallback, IDMapOwnPointer> pending_cert_error_callbacks_;
   IDMap<content::JavaScriptDialogManager::DialogClosedCallback, IDMapOwnPointer>
       pending_js_dialog_callbacks_;
index 27be08b..01f1008 100644 (file)
@@ -197,27 +197,27 @@ bool RegisterXWalkDevToolsServer(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
 
-static jint InitRemoteDebugging(JNIEnv* env,
+static jlong InitRemoteDebugging(JNIEnv* env,
                                 jobject obj,
                                 jstring socketName) {
   XWalkDevToolsServer* server = new XWalkDevToolsServer(
       base::android::ConvertJavaStringToUTF8(env, socketName));
-  return reinterpret_cast<jint>(server);
+  return reinterpret_cast<intptr_t>(server);
 }
 
-static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jint server) {
+static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jlong server) {
   delete reinterpret_cast<XWalkDevToolsServer*>(server);
 }
 
 static jboolean IsRemoteDebuggingEnabled(JNIEnv* env,
                                          jobject obj,
-                                         jint server) {
+                                         jlong server) {
   return reinterpret_cast<XWalkDevToolsServer*>(server)->IsStarted();
 }
 
 static void SetRemoteDebuggingEnabled(JNIEnv* env,
                                       jobject obj,
-                                      jint server,
+                                      jlong server,
                                       jboolean enabled) {
   XWalkDevToolsServer* devtools_server =
       reinterpret_cast<XWalkDevToolsServer*>(server);
@@ -230,7 +230,7 @@ static void SetRemoteDebuggingEnabled(JNIEnv* env,
 
 static void AllowConnectionFromUid(JNIEnv* env,
                                     jobject obj,
-                                    jint server,
+                                    jlong server,
                                     jint uid) {
   XWalkDevToolsServer* devtools_server =
       reinterpret_cast<XWalkDevToolsServer*>(server);
index dccf0cb..27d279f 100644 (file)
@@ -28,7 +28,7 @@ XWalkHttpAuthHandler::XWalkHttpAuthHandler(XWalkLoginDelegate* login_delegate,
   JNIEnv* env = base::android::AttachCurrentThread();
   http_auth_handler_.Reset(
       Java_XWalkHttpAuthHandler_create(
-          env, reinterpret_cast<jint>(this), first_auth_attempt));
+          env, reinterpret_cast<intptr_t>(this), first_auth_attempt));
 }
 
 XWalkHttpAuthHandler:: ~XWalkHttpAuthHandler() {
index c2c6ca1..143239c 100644 (file)
@@ -87,7 +87,7 @@ struct XWalkSettings::FieldIds {
   jfieldID default_video_poster_url;
 };
 
-XWalkSettings::XWalkSettings(JNIEnv* env, jobject obj, jint web_contents)
+XWalkSettings::XWalkSettings(JNIEnv* env, jobject obj, jlong web_contents)
     : WebContentsObserver(
           reinterpret_cast<content::WebContents*>(web_contents)),
       xwalk_settings_(env, obj) {
@@ -98,8 +98,8 @@ XWalkSettings::~XWalkSettings() {
     ScopedJavaLocalRef<jobject> scoped_obj = xwalk_settings_.get(env);
     jobject obj = scoped_obj.obj();
     if (!obj) return;
-    Java_XWalkSettings_nativeXWalkSettingsGone(env, obj,
-                                               reinterpret_cast<jint>(this));
+    Java_XWalkSettings_nativeXWalkSettingsGone(
+        env, obj, reinterpret_cast<intptr_t>(this));
 }
 
 void XWalkSettings::Destroy(JNIEnv* env, jobject obj) {
@@ -224,11 +224,11 @@ void XWalkSettings::RenderViewCreated(
   UpdateEverything();
 }
 
-static jint Init(JNIEnv* env,
+static jlong Init(JNIEnv* env,
                  jobject obj,
-                 jint web_contents) {
+                 jlong web_contents) {
   XWalkSettings* settings = new XWalkSettings(env, obj, web_contents);
-  return reinterpret_cast<jint>(settings);
+  return reinterpret_cast<intptr_t>(settings);
 }
 
 static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
index 60642a8..916f736 100644 (file)
@@ -18,7 +18,7 @@ class XWalkRenderViewHostExt;
 
 class XWalkSettings : public content::WebContentsObserver {
  public:
-  XWalkSettings(JNIEnv* env, jobject obj, jint web_contents);
+  XWalkSettings(JNIEnv* env, jobject obj, jlong web_contents);
   virtual ~XWalkSettings();
 
   // Called from Java.
diff --git a/src/xwalk/runtime/browser/android/xwalk_view_delegate.cc b/src/xwalk/runtime/browser/android/xwalk_view_delegate.cc
new file mode 100644 (file)
index 0000000..1ef20c1
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (c) 2014 Intel 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 "xwalk/runtime/browser/android/xwalk_view_delegate.h"
+
+#include "base/android/jni_android.h"
+#include "jni/XWalkViewDelegate_jni.h"
+
+namespace xwalk {
+
+jboolean IsLibraryBuiltForIA(JNIEnv* env, jclass jcaller) {
+#if defined(ARCH_CPU_X86)
+  return JNI_TRUE;
+#else
+  return JNI_FALSE;
+#endif
+}
+
+bool RegisterXWalkViewDelegate(JNIEnv* env) {
+  return RegisterNativesImpl(env) >= 0;
+}
+
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/android/xwalk_view_delegate.h b/src/xwalk/runtime/browser/android/xwalk_view_delegate.h
new file mode 100644 (file)
index 0000000..73ca615
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 Intel 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 XWALK_RUNTIME_BROWSER_ANDROID_XWALK_VIEW_DELEGATE_H_
+#define XWALK_RUNTIME_BROWSER_ANDROID_XWALK_VIEW_DELEGATE_H_
+
+#include <jni.h>
+
+namespace xwalk {
+
+bool RegisterXWalkViewDelegate(JNIEnv* env);
+
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_BROWSER_ANDROID_XWALK_VIEW_DELEGATE_H_
index 8c57e4f..ecc8459 100644 (file)
@@ -4,17 +4,26 @@
 
 #include "xwalk/runtime/browser/android/xwalk_web_contents_delegate.h"
 
+#include <vector>
+
+#include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/common/file_chooser_params.h"
 #include "jni/XWalkWebContentsDelegate_jni.h"
 #include "xwalk/runtime/browser/media/media_capture_devices_dispatcher.h"
 #include "xwalk/runtime/browser/runtime_file_select_helper.h"
 #include "xwalk/runtime/browser/runtime_javascript_dialog_manager.h"
+#include "ui/shell_dialogs/selected_file_info.h"
 
 using base::android::AttachCurrentThread;
+using base::android::ConvertUTF16ToJavaString;
 using base::android::ScopedJavaLocalRef;
+using content::FileChooserParams;
 using content::WebContents;
 
 namespace xwalk {
@@ -78,7 +87,31 @@ void XWalkWebContentsDelegate::UpdatePreferredSize(
 void XWalkWebContentsDelegate::RunFileChooser(
     content::WebContents* web_contents,
     const content::FileChooserParams& params) {
-  RuntimeFileSelectHelper::RunFileChooser(web_contents, params);
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
+  if (!java_delegate.obj())
+    return;
+
+  if (params.mode == FileChooserParams::Save) {
+    // Save not supported, so cancel it.
+    web_contents->GetRenderViewHost()->FilesSelectedInChooser(
+         std::vector<ui::SelectedFileInfo>(),
+         params.mode);
+    return;
+  }
+  int mode = static_cast<int>(params.mode);
+  jboolean overridden =
+      Java_XWalkWebContentsDelegate_shouldOverrideRunFileChooser(env,
+          java_delegate.obj(),
+          web_contents->GetRenderProcessHost()->GetID(),
+          web_contents->GetRenderViewHost()->GetRoutingID(),
+          mode,
+          ConvertUTF16ToJavaString(env,
+              JoinString(params.accept_types, ',')).obj(),
+          params.capture);
+  if (overridden == JNI_FALSE)
+    RuntimeFileSelectHelper::RunFileChooser(web_contents, params);
 }
 
 content::JavaScriptDialogManager*
index dc0d4d5..3fcd6d6 100644 (file)
@@ -251,7 +251,7 @@ RuntimeFileSelectHelper::GetFileTypesFromAcceptType(
   int valid_type_count = 0;
   int description_id = 0;
   for (size_t i = 0; i < accept_types.size(); ++i) {
-    std::string ascii_type = UTF16ToASCII(accept_types[i]);
+    std::string ascii_type = base::UTF16ToASCII(accept_types[i]);
     if (!IsAcceptTypeValid(ascii_type))
       continue;
 
index 9e9e68e..0280df5 100644 (file)
@@ -4,18 +4,28 @@
 
 #include "xwalk/runtime/browser/runtime_platform_util.h"
 
+#include "base/file_util.h"
 #include "base/logging.h"
 #include "base/process/kill.h"
 #include "base/process/launch.h"
 #include "url/gurl.h"
 
 namespace platform_util {
+namespace {
+// The system default web browser path.
+// In some Tizen releases, there exists a system browser called 'MiniBrowser',
+// which we can use to open an external link from a web app.
+const char kWebBrowserPath[] = "/usr/bin/MiniBrowser";
+}  // namespace
 
 void OpenExternal(const GURL& url) {
   if (url.SchemeIsHTTPOrHTTPS()) {
-    LOG(INFO) << "Open in MiniBrowser.";
+    LOG(INFO) << "Open in WebBrowser.";
     std::vector<std::string> argv;
-    argv.push_back("MiniBrowser");
+    if (base::PathExists(base::FilePath(kWebBrowserPath)))
+      argv.push_back(kWebBrowserPath);
+    else
+      argv.push_back("xwalk");
     argv.push_back(url.spec());
     base::ProcessHandle handle;
 
diff --git a/src/xwalk/runtime/browser/tizen/tizen_locale_listener.cc b/src/xwalk/runtime/browser/tizen/tizen_locale_listener.cc
new file mode 100644 (file)
index 0000000..94b1465
--- /dev/null
@@ -0,0 +1,108 @@
+// 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/tizen/tizen_locale_listener.h"
+
+#include <vconf.h>
+#include <algorithm>
+
+#include "base/logging.h"
+#include "content/public/browser/browser_thread.h"
+#include "xwalk/runtime/browser/xwalk_runner_tizen.h"
+#include "xwalk/application/browser/application_system.h"
+#include "xwalk/application/browser/application_service.h"
+
+namespace xwalk {
+namespace {
+const char kTizenDefaultLocale[] = "en-GB";
+const char kTizenLocaleListenerThreadName[] = "TizenLocaleListener";
+
+bool TizenLocaleToBCP47Locale(const std::string& tizen_locale,
+                              std::string* out_BCP47_locale) {
+  if (tizen_locale.empty())
+    return false;
+
+  // Tizen locale format [language[_territory][.codeset][@modifier]] .
+  // Conver to BCP47 format language[-territory] .
+  *out_BCP47_locale = tizen_locale.substr(0, tizen_locale.find_first_of("."));
+  std::replace(out_BCP47_locale->begin(), out_BCP47_locale->end(), '_', '-');
+  return true;
+}
+
+void OnVconfLangSetChanged(keynode_t *key, void *user_data) {
+  if (vconf_keynode_get_type(key) != VCONF_TYPE_STRING)
+    return;
+  TizenLocaleListener* tizen_locale_listener =
+      static_cast<TizenLocaleListener*>(user_data);
+
+  std::string locale;
+  if (TizenLocaleToBCP47Locale(vconf_keynode_get_str(key), &locale)) {
+    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+        base::Bind(&TizenLocaleListener::SetLocale,
+                   base::Unretained(tizen_locale_listener),
+                   locale));
+  }
+}
+
+std::string GetSystemLocale() {
+  std::string tizen_locale;
+  char* langset = vconf_get_str(VCONFKEY_LANGSET);
+  if (langset) {
+    tizen_locale = langset;
+  } else {
+    LOG(ERROR) << "Can not get VCONFKEY_LANGSET from vconf or "
+               << "VCONFKEY_LANGSET vlaue is not a string value";
+  }
+  free(langset);
+
+  // Tizen take en-GB as default.
+  std::string BCP47_locale(kTizenDefaultLocale);
+  TizenLocaleToBCP47Locale(tizen_locale, &BCP47_locale);
+  return BCP47_locale;
+}
+
+}  // namespace
+
+TizenLocaleListener::TizenLocaleListener()
+    : SimpleThread(kTizenLocaleListenerThreadName),
+      locale_(GetSystemLocale()) {
+  vconf_notify_key_changed(VCONFKEY_LANGSET, OnVconfLangSetChanged, this);
+  main_loop_ = g_main_loop_new(NULL, FALSE);
+  Start();
+}
+
+TizenLocaleListener::~TizenLocaleListener() {
+  g_main_loop_quit(main_loop_);
+  g_main_loop_unref(main_loop_);
+  SimpleThread::Join();
+  vconf_ignore_key_changed(VCONFKEY_LANGSET, OnVconfLangSetChanged);
+}
+
+void TizenLocaleListener::Run() {
+  g_main_loop_run(main_loop_);
+}
+
+std::string TizenLocaleListener::GetLocale() const {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  // Note: we can only get locale from main thread for thread safe.
+  return locale_;
+}
+
+void TizenLocaleListener::SetLocale(const std::string& locale) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  // Note: we can only set locale from main thread for thread safe.
+  // If you need set locale from other thread, please PostTask to main thread.
+  if (locale_ == locale)
+    return;
+
+  LOG(INFO) << "Locale change from " << locale_ << " to " << locale;
+  locale_ = locale;
+
+  application::ApplicationSystem* application_system_ =
+      XWalkRunnerTizen::GetInstance()->app_system();
+  if (application_system_)
+    application_system_->application_service()->ChangeLocale(locale);
+}
+
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/tizen/tizen_locale_listener.h b/src/xwalk/runtime/browser/tizen/tizen_locale_listener.h
new file mode 100644 (file)
index 0000000..e41e742
--- /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.
+
+#ifndef XWALK_RUNTIME_BROWSER_TIZEN_TIZEN_LOCALE_LISTENER_H_
+#define XWALK_RUNTIME_BROWSER_TIZEN_TIZEN_LOCALE_LISTENER_H_
+
+#include <glib.h>
+#include <string>
+
+#include "base/threading/simple_thread.h"
+
+namespace xwalk {
+
+class TizenLocaleListener : public base::SimpleThread {
+  public:
+    TizenLocaleListener();
+    virtual ~TizenLocaleListener();
+
+    virtual void Run() OVERRIDE;
+
+    // Get the latest application locale from system.
+    // locale is a langtag defined in [BCP47]
+    std::string GetLocale() const;
+    // Set the locale and apply this locale to all applications.
+    // Locale is a langtag defined in [BCP47].
+    // This function will called by TizenLocaleListener when locale is changed.
+    void SetLocale(const std::string& locale);
+
+  private:
+    GMainLoop*  main_loop_;
+    // The locale is a langtag defined in [BCP47]
+    std::string locale_;
+};
+
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_BROWSER_TIZEN_TIZEN_LOCALE_LISTENER_H_
index c2bc3a0..65f60a9 100644 (file)
@@ -98,6 +98,7 @@ gfx::Transform NativeAppWindowTizen::GetRotationTransform() const {
   // This method assumed a fixed portrait device. As everything
   // is calculated from the fixed position we do not update the
   // display bounds after rotation change.
+  // FIXME : Add proper support for landscape devices.
   gfx::Transform rotate;
   float one_pixel = 1.0f / display_.device_scale_factor();
   switch (display_.rotation()) {
@@ -123,17 +124,46 @@ gfx::Transform NativeAppWindowTizen::GetRotationTransform() const {
 
 namespace {
 
-// Rotates a binary mask of 4 positions to the left.
-unsigned rotl4(unsigned value, int shift) {
-  unsigned res = (value << shift);
-  if (res > (1 << 4) - 1)
-    res = res >> 4;
-  return res;
+#if defined(OS_TIZEN_MOBILE)
+Orientation ToOrientation(const gfx::Display::Rotation& rotation) {
+  switch (rotation) {
+    case gfx::Display::ROTATE_0:
+      return PORTRAIT_PRIMARY;
+    case gfx::Display::ROTATE_90:
+      return LANDSCAPE_PRIMARY;
+    case gfx::Display::ROTATE_180:
+      return PORTRAIT_SECONDARY;
+    case gfx::Display::ROTATE_270:
+      return LANDSCAPE_SECONDARY;
+    default:
+      NOTREACHED();
+  }
+  return PORTRAIT_PRIMARY;
+}
+#else
+Orientation ToOrientation(const gfx::Display::Rotation& rotation) {
+  switch (rotation) {
+    case gfx::Display::ROTATE_0:
+      return LANDSCAPE_PRIMARY;
+    case gfx::Display::ROTATE_90:
+      return PORTRAIT_PRIMARY;
+    case gfx::Display::ROTATE_180:
+      return LANDSCAPE_SECONDARY;
+    case gfx::Display::ROTATE_270:
+      return PORTRAIT_SECONDARY;
+    default:
+      NOTREACHED();
+  }
+  return LANDSCAPE_PRIMARY;
+}
+#endif
+
+inline gfx::Display::Rotation ToRotation(unsigned rotation) {
+  return static_cast<gfx::Display::Rotation>(rotation % 4);
 }
 
 bool IsLandscapeOrientation(const gfx::Display::Rotation& rotation) {
-  return rotation == gfx::Display::ROTATE_90 ||
-         rotation == gfx::Display::ROTATE_270;
+  return ToOrientation(rotation) & LANDSCAPE;
 }
 
 }  // namespace.
@@ -141,45 +171,28 @@ bool IsLandscapeOrientation(const gfx::Display::Rotation& rotation) {
 gfx::Display::Rotation NativeAppWindowTizen::GetClosestAllowedRotation(
     gfx::Display::Rotation rotation) const {
 
-  unsigned result = PORTRAIT_PRIMARY;
-  // gfx::Display::Rotation starts at portrait-primary and
-  // belongs to the set [0:3].
-  result = rotl4(result, rotation);
-
   // Test current orientation
-  if (allowed_orientations_ & result)
+  if (allowed_orientations_ & ToOrientation(rotation))
     return rotation;
 
   // Test orientation right of current one.
-  if (allowed_orientations_ & rotl4(result, 1))
-    return static_cast<gfx::Display::Rotation>((rotation + 1) % 4);
+  if (allowed_orientations_ & ToOrientation(ToRotation(rotation + 1)))
+    return ToRotation(rotation + 1);
 
   // Test orientation left of current one.
-  if (allowed_orientations_ & rotl4(result, 3))
-    return static_cast<gfx::Display::Rotation>((rotation + 3) % 4);
+  if (allowed_orientations_ & ToOrientation(ToRotation(rotation + 3)))
+    return ToRotation(rotation + 3);
 
   // Test orientation opposite of current one.
-  if (allowed_orientations_ & rotl4(result, 2))
-    return static_cast<gfx::Display::Rotation>((rotation + 2) % 4);
+  if (allowed_orientations_ & ToOrientation(ToRotation(rotation + 1)))
+    return ToRotation(rotation + 1);
 
   NOTREACHED();
   return rotation;
 }
 
 Orientation NativeAppWindowTizen::GetCurrentOrientation() const {
-  switch (display_.rotation()) {
-    case gfx::Display::ROTATE_0:
-      return PORTRAIT_PRIMARY;
-    case gfx::Display::ROTATE_90:
-      return LANDSCAPE_PRIMARY;
-    case gfx::Display::ROTATE_180:
-      return PORTRAIT_SECONDARY;
-    case gfx::Display::ROTATE_270:
-      return LANDSCAPE_SECONDARY;
-    default:
-      NOTREACHED();
-      return PORTRAIT_PRIMARY;
-  }
+  return ToOrientation(display_.rotation());
 }
 
 void NativeAppWindowTizen::OnAllowedOrientationsChanged(
index 1e99918..31da805 100644 (file)
 #include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate_android.h"
 #include "xwalk/runtime/browser/xwalk_browser_main_parts_android.h"
 #include "xwalk/runtime/common/android/xwalk_globals_android.h"
+#else
+#include "xwalk/application/browser/application_system.h"
+#include "xwalk/application/browser/application_service.h"
+#include "xwalk/application/browser/application.h"
 #endif
 
 #if defined(OS_MACOSX)
@@ -44,9 +48,6 @@
 #endif
 
 #if defined(OS_TIZEN)
-#include "xwalk/application/browser/application_system.h"
-#include "xwalk/application/browser/application_service.h"
-#include "xwalk/application/browser/application.h"
 #include "xwalk/application/common/application_manifest_constants.h"
 #include "xwalk/application/common/manifest_handlers/navigation_handler.h"
 #include "xwalk/application/common/constants.h"
@@ -292,49 +293,38 @@ content::SpeechRecognitionManagerDelegate*
   return new xwalk::XWalkSpeechRecognitionManagerDelegate();
 }
 
-#if defined(OS_TIZEN)
-bool XWalkContentBrowserClient::CanCommitURL(
-    content::RenderProcessHost* process_host, const GURL& url) {
+#if !defined(OS_ANDROID)
+bool XWalkContentBrowserClient::CanCreateWindow(const GURL& opener_url,
+                             const GURL& opener_top_level_frame_url,
+                             const GURL& source_origin,
+                             WindowContainerType container_type,
+                             const GURL& target_url,
+                             const content::Referrer& referrer,
+                             WindowOpenDisposition disposition,
+                             const blink::WebWindowFeatures& features,
+                             bool user_gesture,
+                             bool opener_suppressed,
+                             content::ResourceContext* context,
+                             int render_process_id,
+                             bool is_guest,
+                             int opener_id,
+                             bool* no_javascript_access) {
+  *no_javascript_access = false;
   application::Application* app = xwalk_runner_->app_system()->
-      application_service()->GetApplicationByRenderHostID(
-          process_host->GetID());
-  DCHECK(app);
-  const application::ApplicationData* app_data =app->data();
-  if (!app_data->HasCSPDefined() ||
-      (url.SchemeIs(application::kApplicationScheme) &&
-       url.host() == app_data->ID()))
+      application_service()->GetApplicationByRenderHostID(render_process_id);
+  if (!app)
+    // If it's not a request from an application, always enable this action.
     return true;
 
-  application::NavigationInfo* info = static_cast<application::NavigationInfo*>(
-      app_data->GetManifestData(application_widget_keys::kAllowNavigationKey));
-  if (!info || !url.SchemeIsHTTPOrHTTPS()) {
-    LOG(INFO) << "[Block] Navigation link: " << url.spec();
-    // FIXME: Blocked navigation link should be opened in system web browser,
-    // add corresponding code like this:
-    // platform_util::OpenExternal(url);
-    return false;
+  if (app->CanRequestURL(target_url)) {
+    LOG(INFO) << "[ALLOW] CreateWindow: " << target_url.spec();
+    return true;
   }
 
-  // Check whether the navigation url domain is listed in WGT <allow-navigation>
-  // element, if yes, display it in web application, otherwise block the
-  // request.
-  const std::vector<std::string>& allowed_list = info->GetAllowedDomains();
-  for (std::vector<std::string>::const_iterator it = allowed_list.begin();
-       it != allowed_list.end(); ++it) {
-    if ((*it).find("*.") == 0 &&
-        url.DomainIs((*it).substr(2).c_str())) {
-      LOG(INFO) << "[Allow] Navigation link: " << url.spec();
-      return true;
-    }
-
-    if (url.host() == *it) {
-      LOG(INFO) << "[Allow] Navigation link: " << url.spec();
-      return true;
-    }
-  }
-  LOG(INFO) << "[Block] navigation link: " << url.spec();
-  // FIXME: Should open blocked link in system web browser, need to add:
-  // platform_util::OpenExternal(url);
+  LOG(INFO) << "[BlOCK] CreateWindow: " << target_url.spec();
+#if defined(OS_TIZEN)
+  platform_util::OpenExternal(target_url);
+#endif
   return false;
 }
 #endif
index e14ea57..5618aee 100644 (file)
@@ -110,9 +110,22 @@ class XWalkContentBrowserClient : public content::ContentBrowserClient {
       int render_process_id,
       int render_view_id,
       int notification_id) OVERRIDE;
-#if defined(OS_TIZEN)
-  virtual bool CanCommitURL(
-      content::RenderProcessHost* process_host, const GURL& url) OVERRIDE;
+#if !defined(OS_ANDROID)
+  virtual bool CanCreateWindow(const GURL& opener_url,
+                               const GURL& opener_top_level_frame_url,
+                               const GURL& source_origin,
+                               WindowContainerType container_type,
+                               const GURL& target_url,
+                               const content::Referrer& referrer,
+                               WindowOpenDisposition disposition,
+                               const blink::WebWindowFeatures& features,
+                               bool user_gesture,
+                               bool opener_suppressed,
+                               content::ResourceContext* context,
+                               int render_process_id,
+                               bool is_guest,
+                               int opener_id,
+                               bool* no_javascript_access) OVERRIDE;
 #endif
 
 #if defined(OS_ANDROID)
index 975ae56..0a08019 100644 (file)
@@ -17,12 +17,16 @@ bool XWalkRenderMessageFilter::OnMessageReceived(
     const IPC::Message& message,
     bool* message_was_ok) {
   bool handled = true;
+#if !defined(OS_WIN)
   IPC_BEGIN_MESSAGE_MAP_EX(XWalkRenderMessageFilter, message, *message_was_ok)
 #if defined(OS_TIZEN)
     IPC_MESSAGE_HANDLER(ViewMsg_OpenLinkExternal, OnOpenLinkExternal)
 #endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
+#else
+  handled = false;
+#endif
 
   return handled;
 }
index 6e5dae6..c70b350 100644 (file)
@@ -32,6 +32,7 @@ namespace xwalk {
 
 namespace {
 
+const char kDefaultLocale[] = "en-US";
 XWalkRunner* g_xwalk_runner = NULL;
 
 }  // namespace
@@ -86,6 +87,10 @@ void XWalkRunner::PostMainMessageLoopRun() {
   runtime_context_.reset();
 }
 
+std::string XWalkRunner::GetLocale() const {
+  return kDefaultLocale;
+}
+
 void XWalkRunner::CreateComponents() {
   scoped_ptr<ApplicationComponent> app_component(CreateAppComponent());
   // Keep a reference as some code still needs to call
index b411d8a..5f2a7fe 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef XWALK_RUNTIME_BROWSER_XWALK_RUNNER_H_
 #define XWALK_RUNTIME_BROWSER_XWALK_RUNNER_H_
 
+#include <string>
+
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/values.h"
@@ -76,6 +78,10 @@ class XWalkRunner {
   void PreMainMessageLoopRun();
   void PostMainMessageLoopRun();
 
+  // Get the latest application locale from system.
+  // locale is a langtag defined in [BCP47]
+  virtual std::string GetLocale() const;
+
  protected:
   XWalkRunner();
 
index 56bbba6..90db0da 100644 (file)
@@ -19,4 +19,8 @@ XWalkRunnerTizen* XWalkRunnerTizen::GetInstance() {
   return static_cast<XWalkRunnerTizen*>(XWalkRunner::GetInstance());
 }
 
+std::string XWalkRunnerTizen::GetLocale() const {
+  return tizen_locale_listener_.GetLocale();
+}
+
 }  // namespace xwalk
index 2c2ad1f..4d9bbd8 100644 (file)
@@ -5,7 +5,10 @@
 #ifndef XWALK_RUNTIME_BROWSER_XWALK_RUNNER_TIZEN_H_
 #define XWALK_RUNTIME_BROWSER_XWALK_RUNNER_TIZEN_H_
 
+#include <string>
+
 #include "xwalk/runtime/browser/xwalk_runner.h"
+#include "xwalk/runtime/browser/tizen/tizen_locale_listener.h"
 
 namespace xwalk {
 
@@ -20,9 +23,15 @@ class XWalkRunnerTizen : public XWalkRunner {
 
   virtual ~XWalkRunnerTizen();
 
+  // Get the latest application locale from system.
+  // locale is a langtag defined in [BCP47]
+  virtual std::string GetLocale() const OVERRIDE;
+
  private:
   friend class XWalkRunner;
   XWalkRunnerTizen();
+
+  TizenLocaleListener tizen_locale_listener_;
 };
 
 }  // namespace xwalk
index c4dc6ae..df898d1 100644 (file)
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 // Multiply-included file, no traditional include guard.
+#include <string>
+
 #include "xwalk/runtime/common/android/xwalk_hit_test_data.h"
 #include "content/public/common/common_param_traits.h"
 #include "ipc/ipc_channel_handle.h"
@@ -36,71 +38,76 @@ IPC_STRUCT_TRAITS_END()
 // These are messages sent from the browser to the renderer process.
 
 // Tells the renderer to drop all WebCore memory cache.
-IPC_MESSAGE_CONTROL0(XWalkViewMsg_ClearCache)
+IPC_MESSAGE_CONTROL0(XWalkViewMsg_ClearCache) // NOLINT(*)
 
 // Request for the renderer to determine if the document contains any image
 // elements.  The id should be passed in the response message so the response
 // can be associated with the request.
-IPC_MESSAGE_ROUTED1(XWalkViewMsg_DocumentHasImages,
+IPC_MESSAGE_ROUTED1(XWalkViewMsg_DocumentHasImages, // NOLINT(*)
                     int /* id */)
 
 // Do hit test at the given webview coordinate. "Webview" coordinates are
 // physical pixel values with the 0,0 at the top left of the current displayed
 // view (ie 0,0 is not the top left of the page if the page is scrolled).
-IPC_MESSAGE_ROUTED2(XWalkViewMsg_DoHitTest,
+IPC_MESSAGE_ROUTED2(XWalkViewMsg_DoHitTest, // NOLINT(*)
                     int /* view_x */,
                     int /* view_y */)
 
 // Enables receiving pictures from the renderer on every new frame.
-IPC_MESSAGE_ROUTED1(XWalkViewMsg_EnableCapturePictureCallback,
+IPC_MESSAGE_ROUTED1(XWalkViewMsg_EnableCapturePictureCallback, // NOLINT(*)
                     bool /* enable */)
 
 // Requests a new picture with the latest renderer contents synchronously.
 // This message blocks the browser process on the renderer until complete.
-IPC_SYNC_MESSAGE_ROUTED0_0(XWalkViewMsg_CapturePictureSync)
+IPC_SYNC_MESSAGE_ROUTED0_0(XWalkViewMsg_CapturePictureSync) // NOLINT(*)
 
 // Sets the zoom level for text only. Used in layout modes other than
 // Text Autosizing.
-IPC_MESSAGE_ROUTED1(XWalkViewMsg_SetTextZoomLevel,
+IPC_MESSAGE_ROUTED1(XWalkViewMsg_SetTextZoomLevel, // NOLINT(*)
                     double /* zoom_level */)
 
 // Resets WebKit WebView scrolling and scale state. We need to send this
 // message whenever we want to guarantee that page's scale will be
 // recalculated by WebKit.
-IPC_MESSAGE_ROUTED0(XWalkViewMsg_ResetScrollAndScaleState)
+IPC_MESSAGE_ROUTED0(XWalkViewMsg_ResetScrollAndScaleState) // NOLINT(*)
 
 // Sets the initial page scale. This overrides initial scale set by
 // the meta viewport tag.
-IPC_MESSAGE_ROUTED1(XWalkViewMsg_SetInitialPageScale,
+IPC_MESSAGE_ROUTED1(XWalkViewMsg_SetInitialPageScale, // NOLINT(*)
                     double /* page_scale_factor */)
 
 // Set the Javascript online property for network availability change.
-IPC_MESSAGE_CONTROL1(XWalkViewMsg_SetJsOnlineProperty, bool /* network_up */)
+IPC_MESSAGE_CONTROL1(XWalkViewMsg_SetJsOnlineProperty, bool /* network_up */) // NOLINT(*)
+
+// Set the white list for Cross-Origin access.
+IPC_MESSAGE_CONTROL2(XWalkViewMsg_SetOriginAccessWhitelist, // NOLINT(*)
+                     std::string /* base url */,
+                     std::string /* match pattern content*/)
 
 //-----------------------------------------------------------------------------
 // RenderView messages
 // These are messages sent from the renderer to the browser process.
 
 // Response to XWalkViewMsg_DocumentHasImages request.
-IPC_MESSAGE_ROUTED2(XWalkViewHostMsg_DocumentHasImagesResponse,
+IPC_MESSAGE_ROUTED2(XWalkViewHostMsg_DocumentHasImagesResponse, // NOLINT(*)
                     int, /* id */
                     bool /* has_images */)
 
 // Response to XWalkViewMsg_DoHitTest.
-IPC_MESSAGE_ROUTED1(XWalkViewHostMsg_UpdateHitTestData,
+IPC_MESSAGE_ROUTED1(XWalkViewHostMsg_UpdateHitTestData, // NOLINT(*)
                     xwalk::XWalkHitTestData)
 
 // Sent whenever the page scale factor (as seen by RenderView) is changed.
-IPC_MESSAGE_ROUTED1(XWalkViewHostMsg_PageScaleFactorChanged,
+IPC_MESSAGE_ROUTED1(XWalkViewHostMsg_PageScaleFactorChanged, // NOLINT(*)
                     float /* page_scale_factor */)
 
 // Notification that a new picture becomes available. It is only sent if
 // XWalkViewMsg_EnableCapturePictureCallback was previously enabled.
-IPC_MESSAGE_ROUTED0(XWalkViewHostMsg_PictureUpdated)
+IPC_MESSAGE_ROUTED0(XWalkViewHostMsg_PictureUpdated) // NOLINT(*)
 
 // Sent by the renderer when accelerated compositing is enabled, allowing the
 // browser to perform synchronous input event filtering.
-IPC_MESSAGE_ROUTED1(XWalkViewHostMsg_DidActivateAcceleratedCompositing,
+IPC_MESSAGE_ROUTED1(XWalkViewHostMsg_DidActivateAcceleratedCompositing, // NOLINT(*)
                     int /* input_handler_id */)
 
 
index 1dff0f0..4be6894 100644 (file)
@@ -8,6 +8,7 @@
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_platform_file.h"
 #include "url/gurl.h"
+#include "xwalk/application/common/security_policy.h"
 
 // Singly-included section for enums and custom IPC traits.
 #ifndef XWALK_RUNTIME_COMMON_XWALK_COMMON_MESSAGES_H_
@@ -23,6 +24,7 @@ namespace IPC {
 
 #define IPC_MESSAGE_START ViewMsgStart
 
+IPC_ENUM_TRAITS(xwalk::application::SecurityPolicy::SecurityMode)
 //-----------------------------------------------------------------------------
 // RenderView messages
 // These are messages sent from the browser to the renderer process.
@@ -32,8 +34,12 @@ IPC_MESSAGE_CONTROL3(ViewMsg_SetAccessWhiteList,  // NOLINT
                      GURL /* dest */,
                      bool /* allow_subdomains */)
 
-IPC_MESSAGE_CONTROL1(ViewMsg_EnableWarpMode,    // NOLINT
-                     GURL /* application url */)
+IPC_MESSAGE_CONTROL2(ViewMsg_EnableSecurityMode,    // NOLINT
+                     GURL /* application url */,
+                     xwalk::application::SecurityPolicy::SecurityMode
+                     /* security mode */)
+
+IPC_MESSAGE_ROUTED1(ViewMsg_HWKeyPressed, int /*keycode*/)  // NOLINT
 
 // These are messages sent from the renderer to the browser process.
 #if defined(OS_TIZEN)
diff --git a/src/xwalk/runtime/common/xwalk_localized_error.cc b/src/xwalk/runtime/common/xwalk_localized_error.cc
new file mode 100644 (file)
index 0000000..a19dc89
--- /dev/null
@@ -0,0 +1,241 @@
+// 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 "xwalk/runtime/common/xwalk_localized_error.h"
+
+#include "base/i18n/rtl.h"
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/net/net_error_info.h"
+#include "grit/xwalk_resources.h"
+#include "net/base/escape.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "url/gurl.h"
+
+using blink::WebURLError;
+
+namespace {
+
+struct LocalizedErrorMap {
+  int error_code;
+  unsigned int details_resource_id;
+};
+
+const LocalizedErrorMap net_error_options[] = {
+  { net::ERR_TIMED_OUT,
+    IDS_ERRORPAGES_DETAILS_TIMED_OUT,
+  },
+  { net::ERR_CONNECTION_TIMED_OUT,
+    IDS_ERRORPAGES_DETAILS_TIMED_OUT,
+  },
+  { net::ERR_CONNECTION_CLOSED,
+    IDS_ERRORPAGES_DETAILS_CONNECTION_CLOSED,
+  },
+  { net::ERR_CONNECTION_RESET,
+    IDS_ERRORPAGES_DETAILS_CONNECTION_RESET,
+  },
+  { net::ERR_CONNECTION_REFUSED,
+    IDS_ERRORPAGES_DETAILS_CONNECTION_REFUSED,
+  },
+  { net::ERR_CONNECTION_FAILED,
+    IDS_ERRORPAGES_DETAILS_CONNECTION_FAILED,
+  },
+  { net::ERR_NAME_NOT_RESOLVED,
+    IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED,
+  },
+  { net::ERR_ADDRESS_UNREACHABLE,
+    IDS_ERRORPAGES_DETAILS_ADDRESS_UNREACHABLE,
+  },
+  { net::ERR_NETWORK_ACCESS_DENIED,
+    IDS_ERRORPAGES_DETAILS_NETWORK_ACCESS_DENIED,
+  },
+  { net::ERR_PROXY_CONNECTION_FAILED,
+    IDS_ERRORPAGES_DETAILS_PROXY_CONNECTION_FAILED,
+  },
+  { net::ERR_INTERNET_DISCONNECTED,
+    IDS_ERRORPAGES_DETAILS_INTERNET_DISCONNECTED,
+  },
+  { net::ERR_FILE_NOT_FOUND,
+    IDS_ERRORPAGES_DETAILS_FILE_NOT_FOUND,
+  },
+  { net::ERR_CACHE_MISS,
+    IDS_ERRORPAGES_DETAILS_CACHE_MISS,
+  },
+  { net::ERR_CACHE_READ_FAILURE,
+    IDS_ERRORPAGES_DETAILS_CACHE_READ_FAILURE,
+  },
+  { net::ERR_NETWORK_IO_SUSPENDED,
+    IDS_ERRORPAGES_DETAILS_NETWORK_IO_SUSPENDED,
+  },
+  { net::ERR_TOO_MANY_REDIRECTS,
+    IDS_ERRORPAGES_DETAILS_TOO_MANY_REDIRECTS,
+  },
+  { net::ERR_EMPTY_RESPONSE,
+    IDS_ERRORPAGES_DETAILS_EMPTY_RESPONSE,
+  },
+  { net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH,
+    IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH,
+  },
+  { net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION,
+    IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION,
+  },
+  { net::ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION,
+    IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_LOCATION,
+  },
+  { net::ERR_CONTENT_LENGTH_MISMATCH,
+    IDS_ERRORPAGES_DETAILS_CONNECTION_CLOSED,
+  },
+  { net::ERR_INCOMPLETE_CHUNKED_ENCODING,
+    IDS_ERRORPAGES_DETAILS_CONNECTION_CLOSED,
+  },
+  { net::ERR_SSL_PROTOCOL_ERROR,
+    IDS_ERRORPAGES_DETAILS_SSL_PROTOCOL_ERROR,
+  },
+  { net::ERR_SSL_UNSAFE_NEGOTIATION,
+    IDS_ERRORPAGES_DETAILS_SSL_UNSAFE_NEGOTIATION,
+  },
+  { net::ERR_BAD_SSL_CLIENT_AUTH_CERT,
+    IDS_ERRORPAGES_DETAILS_BAD_SSL_CLIENT_AUTH_CERT,
+  },
+  { net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY,
+    IDS_ERRORPAGES_DETAILS_SSL_PROTOCOL_ERROR,
+  },
+  { net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN,
+    IDS_ERRORPAGES_DETAILS_PINNING_FAILURE,
+  },
+  { net::ERR_TEMPORARILY_THROTTLED,
+    IDS_ERRORPAGES_DETAILS_TEMPORARILY_THROTTLED,
+  },
+  { net::ERR_BLOCKED_BY_CLIENT,
+    IDS_ERRORPAGES_DETAILS_BLOCKED,
+  },
+  { net::ERR_NETWORK_CHANGED,
+    IDS_ERRORPAGES_DETAILS_NETWORK_CHANGED,
+  },
+  { net::ERR_BLOCKED_BY_ADMINISTRATOR,
+    IDS_ERRORPAGES_DETAILS_BLOCKED_BY_ADMINISTRATOR,
+  },
+};
+
+// Special error page to be used in the case of navigating back to a page
+// generated by a POST.  LocalizedError::HasStrings expects this net error code
+// to also appear in the array above.
+
+const LocalizedErrorMap repost_error = {
+  net::ERR_CACHE_MISS,
+  IDS_ERRORPAGES_DETAILS_CACHE_MISS,
+};
+
+const LocalizedErrorMap http_error_options[] = {
+  { 403,
+    IDS_ERRORPAGES_DETAILS_FORBIDDEN,
+  },
+  { 410,
+    IDS_ERRORPAGES_DETAILS_GONE,
+  },
+
+  { 500,
+    IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR,
+  },
+  { 501,
+    IDS_ERRORPAGES_DETAILS_NOT_IMPLEMENTED,
+  },
+  { 502,
+    IDS_ERRORPAGES_DETAILS_BAD_GATEWAY,
+  },
+  { 503,
+    IDS_ERRORPAGES_DETAILS_SERVICE_UNAVAILABLE,
+  },
+  { 504,
+    IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT,
+  },
+  { 505,
+    IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED,
+  },
+};
+
+const LocalizedErrorMap dns_probe_error_options[] = {
+  { chrome_common_net::DNS_PROBE_POSSIBLE,
+    IDS_ERRORPAGES_DETAILS_DNS_PROBE_RUNNING,
+  },
+
+  // DNS_PROBE_NOT_RUN is not here; NetErrorHelper will restore the original
+  // error, which might be one of several DNS-related errors.
+
+  { chrome_common_net::DNS_PROBE_STARTED,
+    IDS_ERRORPAGES_DETAILS_DNS_PROBE_RUNNING,
+  },
+
+  // DNS_PROBE_FINISHED_UNKNOWN is not here; NetErrorHelper will restore the
+  // original error, which might be one of several DNS-related errors.
+
+  { chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET,
+    IDS_ERRORPAGES_DETAILS_INTERNET_DISCONNECTED,
+  },
+  { chrome_common_net::DNS_PROBE_FINISHED_BAD_CONFIG,
+    IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED,
+  },
+  { chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN,
+    IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED,
+  },
+};
+
+const LocalizedErrorMap* FindErrorMapInArray(const LocalizedErrorMap* maps,
+                                                   size_t num_maps,
+                                                   int error_code) {
+  for (size_t i = 0; i < num_maps; ++i) {
+    if (maps[i].error_code == error_code)
+      return &maps[i];
+  }
+  return NULL;
+}
+
+const LocalizedErrorMap* LookupErrorMap(const std::string& error_domain,
+                                        int error_code, bool is_post) {
+  if (error_domain == net::kErrorDomain) {
+    // Display a different page in the special case of navigating through the
+    // history to an uncached page created by a POST.
+    if (is_post && error_code == net::ERR_CACHE_MISS)
+      return &repost_error;
+    return FindErrorMapInArray(net_error_options,
+                               arraysize(net_error_options),
+                               error_code);
+  } else if (error_domain == LocalizedError::kHttpErrorDomain) {
+    return FindErrorMapInArray(http_error_options,
+                               arraysize(http_error_options),
+                               error_code);
+  } else if (error_domain == LocalizedError::kDnsProbeErrorDomain) {
+    const LocalizedErrorMap* map =
+        FindErrorMapInArray(dns_probe_error_options,
+                            arraysize(dns_probe_error_options),
+                            error_code);
+    DCHECK(map);
+    return map;
+  } else {
+    NOTREACHED();
+    return NULL;
+  }
+}
+}  // namespace
+
+const char LocalizedError::kHttpErrorDomain[] = "http";
+const char LocalizedError::kDnsProbeErrorDomain[] = "dnsprobe";
+
+base::string16 LocalizedError::GetErrorDetails(const blink::WebURLError& error,
+                                               bool is_post) {
+  const LocalizedErrorMap* error_map =
+      LookupErrorMap(error.domain.utf8(), error.reason, is_post);
+  if (error_map)
+    return l10n_util::GetStringUTF16(error_map->details_resource_id);
+  else
+    return l10n_util::GetStringUTF16(IDS_ERRORPAGES_DETAILS_UNKNOWN);
+}
diff --git a/src/xwalk/runtime/common/xwalk_localized_error.h b/src/xwalk/runtime/common/xwalk_localized_error.h
new file mode 100644 (file)
index 0000000..9810cce
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 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 XWALK_RUNTIME_COMMON_XWALK_LOCALIZED_ERROR_H_
+#define XWALK_RUNTIME_COMMON_XWALK_LOCALIZED_ERROR_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+
+class GURL;
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace blink {
+struct WebURLError;
+}
+
+class LocalizedError {
+ public:
+  // Returns a description of the encountered error.
+  static base::string16 GetErrorDetails(const blink::WebURLError& error,
+                                        bool is_post);
+
+  static const char kHttpErrorDomain[];
+  static const char kDnsProbeErrorDomain[];
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(LocalizedError);
+};
+
+#endif  // XWALK_RUNTIME_COMMON_XWALK_LOCALIZED_ERROR_H_
index 45e6c56..7f1bd2c 100644 (file)
@@ -4,9 +4,15 @@
 
 #include "xwalk/runtime/renderer/android/xwalk_render_process_observer.h"
 
+#include "base/json/json_reader.h"
+#include "base/values.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/url_pattern.h"
 #include "ipc/ipc_message_macros.h"
 #include "third_party/WebKit/public/web/WebCache.h"
 #include "third_party/WebKit/public/web/WebNetworkStateNotifier.h"
+#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
+#include "xwalk/runtime/browser/android/net/url_constants.h"
 #include "xwalk/runtime/common/android/xwalk_render_view_messages.h"
 
 namespace xwalk {
@@ -24,6 +30,8 @@ bool XWalkRenderProcessObserver::OnControlMessageReceived(
   IPC_BEGIN_MESSAGE_MAP(XWalkRenderProcessObserver, message)
     IPC_MESSAGE_HANDLER(XWalkViewMsg_SetJsOnlineProperty, OnSetJsOnlineProperty)
     IPC_MESSAGE_HANDLER(XWalkViewMsg_ClearCache, OnClearCache);
+    IPC_MESSAGE_HANDLER(XWalkViewMsg_SetOriginAccessWhitelist,
+                        OnSetOriginAccessWhitelist)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -43,4 +51,49 @@ void XWalkRenderProcessObserver::OnClearCache() {
     blink::WebCache::clear();
 }
 
+void XWalkRenderProcessObserver::OnSetOriginAccessWhitelist(
+    std::string base_url,
+    std::string match_patterns) {
+  blink::WebSecurityPolicy::resetOriginAccessWhitelists();
+
+  DCHECK(!base_url.empty());
+  if (base_url.empty() || match_patterns.empty())
+    return;
+
+  base::Value* patterns = base::JSONReader::Read(match_patterns);
+  if (!patterns)
+    return;
+
+  base::ListValue* match_pattern_list = NULL;
+  if (!patterns->GetAsList(&match_pattern_list))
+    return;
+
+  const char* schemes[] = {
+    content::kHttpScheme,
+    content::kHttpsScheme,
+    content::kFileScheme,
+    xwalk::kAppScheme,
+  };
+  size_t size = match_pattern_list->GetSize();
+  for (size_t i = 0; i < size; i ++) {
+    std::string match_pattern;
+    if (!match_pattern_list->GetString(i, &match_pattern))
+      continue;
+
+    URLPattern allowedUrl(URLPattern::SCHEME_ALL);
+    if (allowedUrl.Parse(match_pattern) != URLPattern::PARSE_SUCCESS)
+      continue;
+
+    for (size_t j = 0; j < arraysize(schemes); ++j) {
+      if (allowedUrl.MatchesScheme(schemes[j])) {
+        blink::WebSecurityPolicy::addOriginAccessWhitelistEntry(
+              blink::WebURL(GURL(base_url)),
+              blink::WebString::fromUTF8(schemes[j]),
+              blink::WebString::fromUTF8(allowedUrl.host()),
+              allowedUrl.match_subdomains());
+      }
+    }
+  }
+}
+
 }  // namespace xwalk
index 585d0e0..7412bbc 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef XWALK_RUNTIME_RENDERER_ANDROID_XWALK_RENDER_PROCESS_OBSERVER_H_
 #define XWALK_RUNTIME_RENDERER_ANDROID_XWALK_RENDER_PROCESS_OBSERVER_H_
 
+#include <string>
+
 #include "content/public/renderer/render_process_observer.h"
 
 #include "base/compiler_specific.h"
@@ -25,6 +27,8 @@ class XWalkRenderProcessObserver : public content::RenderProcessObserver {
  private:
   void OnSetJsOnlineProperty(bool network_up);
   void OnClearCache();
+  void OnSetOriginAccessWhitelist(std::string base_url,
+                                  std::string match_patterns);
 
   bool webkit_initialized_;
 };
diff --git a/src/xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.cc b/src/xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.cc
new file mode 100644 (file)
index 0000000..0ba1155
--- /dev/null
@@ -0,0 +1,90 @@
+// 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 "xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/renderer/render_frame.h"
+#include "content/public/renderer/render_view.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebScriptSource.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#include "xwalk/runtime/common/xwalk_common_messages.h"
+
+namespace {
+std::string GenerateEventJs(const std::string& name) {
+  std::string result;
+  std::string defineJs =
+    "var event = new Event('tizenhwkey');"
+    "function defineProps(val) {"
+    "  Object.defineProperty(event, 'keyName', {"
+    "    enumerable: false,"
+    "    configurable: false,"
+    "    writable: false,"
+    "    value: val"
+    "  });"
+    "}";
+  std::string nameJs = "defineProps('" + name + "');";
+  std::string dispatchJs = "document.dispatchEvent(event);";
+  result += defineJs;
+  result += nameJs;
+  result += dispatchJs;
+
+  return result;
+}
+}  // namespace
+
+namespace xwalk {
+
+XWalkRenderViewExtTizen::XWalkRenderViewExtTizen(
+    content::RenderView* render_view)
+    : content::RenderViewObserver(render_view) {
+  render_view_ = render_view;
+  DCHECK(render_view_);
+}
+
+XWalkRenderViewExtTizen::~XWalkRenderViewExtTizen() {
+}
+
+// static
+void XWalkRenderViewExtTizen::RenderViewCreated(
+    content::RenderView* render_view) {
+  new XWalkRenderViewExtTizen(render_view);  // |render_view| takes ownership.
+}
+
+bool XWalkRenderViewExtTizen::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(XWalkRenderViewExtTizen, message)
+    IPC_MESSAGE_HANDLER(ViewMsg_HWKeyPressed,
+                        OnHWKeyPressed)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void XWalkRenderViewExtTizen::OnHWKeyPressed(int keycode) {
+  std::string event_name;
+  if (keycode == ui::VKEY_BACK) {
+    event_name = "back";
+  } else if (keycode == ui::VKEY_HOME) {
+    event_name = "menu";
+  } else {
+    LOG(INFO) << "Unknown input key code, only support 'back' & 'menu'"
+                  "at present.";
+    return;
+  }
+
+  content::RenderFrame* render_frame = render_view_->GetMainRenderFrame();
+  blink::WebFrame* web_frame = render_frame->GetWebFrame();
+  blink::WebScriptSource source =
+      blink::WebScriptSource(base::ASCIIToUTF16(GenerateEventJs(event_name)));
+  web_frame->executeScript(source);
+}
+
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.h b/src/xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.h
new file mode 100644 (file)
index 0000000..1181e5d
--- /dev/null
@@ -0,0 +1,33 @@
+// 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 XWALK_RUNTIME_RENDERER_TIZEN_XWALK_RENDER_VIEW_EXT_TIZEN_H_
+#define XWALK_RUNTIME_RENDERER_TIZEN_XWALK_RENDER_VIEW_EXT_TIZEN_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "content/public/renderer/render_view_observer.h"
+
+namespace xwalk {
+
+class XWalkRenderViewExtTizen : public content::RenderViewObserver {
+ public:
+  static void RenderViewCreated(content::RenderView* render_view);
+
+ private:
+  explicit XWalkRenderViewExtTizen(content::RenderView* render_view);
+  virtual ~XWalkRenderViewExtTizen();
+
+  // RenderView::Observer:
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+  void OnHWKeyPressed(int keycode);
+
+  content::RenderView* render_view_;
+  DISALLOW_COPY_AND_ASSIGN(XWalkRenderViewExtTizen);
+};
+
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_RENDERER_TIZEN_XWALK_RENDER_VIEW_EXT_TIZEN_H_
index b084d7e..0f28aa3 100644 (file)
 #include "grit/xwalk_application_resources.h"
 #include "grit/xwalk_sysapps_resources.h"
 #include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
 #include "xwalk/application/common/constants.h"
 #include "xwalk/application/renderer/application_native_module.h"
 #include "xwalk/extensions/renderer/xwalk_js_module.h"
+#include "xwalk/runtime/common/xwalk_localized_error.h"
 
 #if defined(OS_ANDROID)
 #include "xwalk/runtime/renderer/android/xwalk_permission_client.h"
 #include "xwalk/runtime/renderer/tizen/xwalk_content_renderer_client_tizen.h"
 #endif
 
+#if defined(OS_TIZEN)
+#include "xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.h"
+#endif
+
 namespace xwalk {
 
 namespace {
@@ -111,6 +117,8 @@ void XWalkContentRendererClient::RenderViewCreated(
     content::RenderView* render_view) {
 #if defined(OS_ANDROID)
   XWalkRenderViewExt::RenderViewCreated(render_view);
+#elif defined(OS_TIZEN)
+  XWalkRenderViewExtTizen::RenderViewCreated(render_view);
 #endif
 }
 
@@ -158,22 +166,42 @@ bool XWalkContentRendererClient::WillSendRequest(blink::WebFrame* frame,
 #if defined(OS_ANDROID)
   return false;
 #else
-  if (!xwalk_render_process_observer_->IsWarpMode())
+  if (!xwalk_render_process_observer_->IsWarpMode()
+#if defined(OS_TIZEN)
+      && !xwalk_render_process_observer_->IsCSPMode()
+#endif
+      )
     return false;
 
   GURL origin_url(frame->document().url());
   GURL app_url(xwalk_render_process_observer_->app_url());
-  if ((url.scheme() == app_url.scheme() &&
-       url.host() == app_url.host()) ||
+#if defined(OS_TIZEN)
+  // if under CSP mode.
+  if (xwalk_render_process_observer_->IsCSPMode()) {
+    if (url.GetOrigin() != app_url.GetOrigin() &&
+        origin_url != first_party_for_cookies &&
+        first_party_for_cookies.GetOrigin() != app_url.GetOrigin() &&
+        !frame->document().securityOrigin().canRequest(url)) {
+      LOG(INFO) << "[BLOCK] allow-navigation: " << url.spec();
+      content::RenderThread::Get()->Send(new ViewMsg_OpenLinkExternal(url));
+      *new_url = GURL();
+      return true;
+    }
+    return false;
+  }
+#endif
+  // if under WARP mode.
+  if (url.GetOrigin() == app_url.GetOrigin() ||
       frame->document().securityOrigin().canRequest(url)) {
     LOG(INFO) << "[PASS] " << origin_url.spec() << " request " << url.spec();
     return false;
   }
 
   LOG(INFO) << "[BLOCK] " << origin_url.spec() << " request " << url.spec();
-
 #if defined(OS_TIZEN)
-  if (origin_url.spec().empty())
+  if (url.GetOrigin() != app_url.GetOrigin() &&
+      origin_url != first_party_for_cookies &&
+      first_party_for_cookies.GetOrigin() != app_url.GetOrigin())
     content::RenderThread::Get()->Send(new ViewMsg_OpenLinkExternal(url));
 #endif
 
@@ -181,4 +209,21 @@ bool XWalkContentRendererClient::WillSendRequest(blink::WebFrame* frame,
   return true;
 #endif
 }
+
+void XWalkContentRendererClient::GetNavigationErrorStrings(
+    content::RenderView* render_view,
+    blink::WebFrame* frame,
+    const blink::WebURLRequest& failed_request,
+    const blink::WebURLError& error,
+    std::string* error_html,
+    base::string16* error_description) {
+  bool is_post = EqualsASCII(failed_request.httpMethod(), "POST");
+
+  // TODO(guangzhen): Check whether error_html is needed in xwalk runtime.
+
+  if (error_description) {
+    *error_description = LocalizedError::GetErrorDetails(error, is_post);
+  }
+}
+
 }  // namespace xwalk
index f3fc4cc..609ff18 100644 (file)
@@ -5,9 +5,12 @@
 #ifndef XWALK_RUNTIME_RENDERER_XWALK_CONTENT_RENDERER_CLIENT_H_
 #define XWALK_RUNTIME_RENDERER_XWALK_CONTENT_RENDERER_CLIENT_H_
 
+#include <string>
+
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
+#include "base/strings/string16.h"
 #include "content/public/common/page_transition_types.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "xwalk/extensions/renderer/xwalk_extension_renderer_controller.h"
@@ -68,6 +71,14 @@ class XWalkContentRendererClient
   scoped_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
 #endif
 
+  void GetNavigationErrorStrings(
+      content::RenderView* render_view,
+      blink::WebFrame* frame,
+      const blink::WebURLRequest& failed_request,
+      const blink::WebURLError& error,
+      std::string* error_html,
+      base::string16* error_description) OVERRIDE;
+
   DISALLOW_COPY_AND_ASSIGN(XWalkContentRendererClient);
 };
 
index e459450..de6b5a6 100644 (file)
@@ -44,7 +44,7 @@ void AddAccessWhiteListEntry(
 
 XWalkRenderProcessObserver::XWalkRenderProcessObserver()
     : is_webkit_initialized_(false),
-      is_warp_mode_(false) {
+      security_mode_(application::SecurityPolicy::NoSecurity) {
 }
 
 XWalkRenderProcessObserver::~XWalkRenderProcessObserver() {
@@ -55,7 +55,7 @@ bool XWalkRenderProcessObserver::OnControlMessageReceived(
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(XWalkRenderProcessObserver, message)
     IPC_MESSAGE_HANDLER(ViewMsg_SetAccessWhiteList, OnSetAccessWhiteList)
-    IPC_MESSAGE_HANDLER(ViewMsg_EnableWarpMode, OnEnableWarpMode)
+    IPC_MESSAGE_HANDLER(ViewMsg_EnableSecurityMode, OnEnableSecurityMode)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -89,9 +89,10 @@ void XWalkRenderProcessObserver::OnSetAccessWhiteList(const GURL& source,
         AccessWhitelistItem(source, dest, allow_subdomains));
 }
 
-void XWalkRenderProcessObserver::OnEnableWarpMode(const GURL& url) {
+void XWalkRenderProcessObserver::OnEnableSecurityMode(
+    const GURL& url, application::SecurityPolicy::SecurityMode mode) {
   app_url_ = url;
-  is_warp_mode_ = true;
+  security_mode_ = mode;
 }
 
 }  // namespace xwalk
index 4e6f95c..eb0efc2 100644 (file)
@@ -11,6 +11,7 @@
 #include "content/public/renderer/render_process_observer.h"
 #include "url/gurl.h"
 #include "v8/include/v8.h"
+#include "xwalk/application/common/security_policy.h"
 
 namespace blink {
 class WebFrame;
@@ -36,16 +37,23 @@ class XWalkRenderProcessObserver : public content::RenderProcessObserver {
   virtual void WebKitInitialized() OVERRIDE;
   virtual void OnRenderProcessShutdown() OVERRIDE;
 
-  bool IsWarpMode() const { return is_warp_mode_; }
+  bool IsWarpMode() const {
+    return security_mode_ == application::SecurityPolicy::WARP;
+  }
+  bool IsCSPMode() const {
+    return security_mode_ == application::SecurityPolicy::CSP;
+  }
+
   const GURL& app_url() const { return app_url_; }
 
  private:
   void OnSetAccessWhiteList(
       const GURL& source, const GURL& dest, bool allow_subdomains);
-  void OnEnableWarpMode(const GURL& url);
+  void OnEnableSecurityMode(
+      const GURL& url, application::SecurityPolicy::SecurityMode mode);
 
   bool is_webkit_initialized_;
-  bool is_warp_mode_;
+  application::SecurityPolicy::SecurityMode security_mode_;
   GURL app_url_;
 };
 }  // namespace xwalk
index ce0750d..e8c842c 100644 (file)
       <message name="IDS_SELECT_COLOR_DIALOG_TITLE" desc="The default title for the Select Color color chooser dialog.">
         Select Color
       </message>
+      <!-- error messages for network errors -->
+      <message name="IDS_ERRORPAGES_DETAILS_TIMED_OUT" desc="The error message displayed when a page takes too long to load.">
+        The operation timed out.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_CONNECTION_CLOSED" desc="The error message displayed when the server unexpectedly closes a connection.">
+        The server unexpectedly closed the connection.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_CONNECTION_RESET" desc="The error message displayed when a connection was reset.">
+        The connection was reset.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_CONNECTION_REFUSED" desc="The error message displayed when we try and connect to a server, but the server doesn't let us.">
+        The server refused the connection.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_CONNECTION_FAILED" desc="The error message displayed when we can not reach the website.">
+        The attempt to connect to the server failed.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_NETWORK_CHANGED" desc="The error message displayed when a connection is interrupted because the network changed.">
+        A network change was detected.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED" desc="The error message displayed when a dns look up fails.">
+        Unable to resolve the server's DNS address.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_ADDRESS_UNREACHABLE" desc="The error message displayed when we can't reach a server.">
+        Unable to reach the server.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_NETWORK_ACCESS_DENIED" desc="The error message displayed when we're not being allowed to access the network.">
+        Unable to access the network.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_FILE_ACCESS_DENIED" desc="The error message displayed when we're not being allowed to access a file.">
+        Unable to access the file.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_PROXY_CONNECTION_FAILED" desc="The error message displayed when the proxy server connection failed.">
+        Proxy server connection failed.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_INTERNET_DISCONNECTED" desc="The error message displayed when we have no Internet access.">
+        The Internet connection has been lost.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_CACHE_READ_FAILURE" desc="The error message displayed when we encountered an error reading from the cache.  Generally this happens when the disk cache is corrupted from improper shutdown.">
+        Error reading data from cache.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_CACHE_MISS" desc="The error message displayed when we couldn't find a resource in the cache, and cannot fall back to the network.">
+        The requested entry was not found in the cache.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_NETWORK_IO_SUSPENDED" desc="The error message displayed when a page load failed due to the computer entering sleep/suspend mode.">
+        Network IO suspended.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_FILE_NOT_FOUND" desc="The error message displayed when a local file can not be found.">
+        The file or directory could not be found.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_TOO_MANY_REDIRECTS" desc="The error message displayed when there are too many redirects.">
+        There were too many redirects.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_EMPTY_RESPONSE" desc="The error message displayed when no data is received.">
+        The server closed the connection without sending any data.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH" desc="The error message displayed when we received multiple 'Content-Length' header fields in an http response.">
+        Multiple distinct Content-Length headers received.  This is disallowed
+        to protect against HTTP response splitting attacks.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION" desc="The error message displayed when we received multiple 'Content-Disposition' header fields in an http response.">
+        Multiple distinct Content-Disposition headers received.  This is disallowed to
+        protect against HTTP response splitting attacks.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_LOCATION" desc="The error message displayed when we received multiple 'Location' header fields in an http response.">
+        Multiple distinct Location headers received.  This is disallowed to protect
+        against HTTP response splitting attacks.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_DNS_PROBE_RUNNING" desc="The error message displayed when we are waiting to see whether we will run a DNS probe.">
+        Waiting for DNS probe.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_UNKNOWN" desc="The default error message displayed if we don't have a more specific error message.">
+        Unknown error.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_SSL_PROTOCOL_ERROR" desc="The error message displayed for SSL protocol errors.">
+        SSL protocol error.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_SSL_UNSAFE_NEGOTIATION" desc="The error message displayed when the SSL renegotiation extension is missing.">
+        The SSL renegotiation extension was missing from the secure handshake. For some sites, which are known to support the renegotiation extension, Chrome requires a more secure handshake to prevent a class of known attacks. The omission of this extension suggests that your connection was intercepted and manipulated in transit.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_BAD_SSL_CLIENT_AUTH_CERT" desc="The error message for SSL client certificate authentication failure.">
+        Bad SSL client authentication certificate.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_TEMPORARILY_THROTTLED" desc="The error message displayed when we temporarily stop sending requests to a server in order to avoid DDoS.">
+        Extension requests to this URL have been temporarily throttled.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_PINNING_FAILURE" desc="Description of the error page for a certificate which doesn't match the built-in pins for that name">
+        The server's certificate appears to be a forgery.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_BLOCKED" desc="The error message displayed when an extension blocks a request.">
+        Requests to the server have been blocked by an extension.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_BLOCKED_BY_ADMINISTRATOR" desc="The error message displayed when a policy blocks a request.">
+        Requests to the server have been blocked by a policy.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_FORBIDDEN" desc="Details in the error page when a server returns a 403.">
+        The server refused to fulfill the request.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_GONE" desc="Details in the error page when a server returns a 410.">
+        The requested resource no longer exists, and there is no forwarding address.  This is expected to be a permanent condition.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR" desc="The error message displayed when the server returns a 500.">
+        An unexpected condition was encountered while the server was attempting to fulfill the request.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_NOT_IMPLEMENTED" desc="The error message displayed when the server returns a 501.">
+        The server does not support the functionality required to fulfill the request.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_BAD_GATEWAY" desc="The error message displayed when the server returns a 502.">
+        The gateway or proxy server received an invalid response from an upstream server.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_SERVICE_UNAVAILABLE" desc="The error message displayed when the server returns a 503.">
+        The server is currently unable to handle the request.  This code indicates this is a temporary condition, and the server will be up again after a delay.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT" desc="The error message displayed when the server returns a 504.">
+        The gateway or proxy server timed out while waiting for a response from an upstream server.
+      </message>
+      <message name="IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED" desc="The error message displayed when the server returns a 505.">
+        The server does not support the HTTP version used in the request.
+      </message>
     </messages>
   </release>
   <translations />
index a0b6f0a..0f57fa3 100644 (file)
@@ -21,6 +21,7 @@
     <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.READ_LOGS"/>
     <uses-permission android:name="android.permission.WAKE_LOCK" />
 </manifest>
index 3a31d41..9055994 100644 (file)
@@ -40,10 +40,11 @@ public class GeolocationPermissionTest extends XWalkViewTestBase {
     public void testGeolocationPermissionShowPrompt() throws Throwable {
         class TestWebChromeClient extends XWalkWebChromeClient {
             public TestWebChromeClient() {
-                super(getXWalkView().getContext(), getXWalkView());
+                super(getXWalkView());
             }
 
             private int mCalledCount = 0;
+
             @Override
             public void onGeolocationPermissionsShowPrompt(String origin,
                     XWalkGeolocationPermissions.Callback callback) {
@@ -76,7 +77,7 @@ public class GeolocationPermissionTest extends XWalkViewTestBase {
     public void testGeolocationPermissionHidePrompt() throws Throwable {
         class TestWebChromeClient extends XWalkWebChromeClient {
             public TestWebChromeClient() {
-                super(getXWalkView().getContext(), getXWalkView());
+                super(getXWalkView());
             }
 
             @Override
index c6ca89d..338fef8 100644 (file)
@@ -10,6 +10,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.test.suitebuilder.annotation.SmallTest;
+
 import org.chromium.base.test.util.Feature;
 import org.xwalk.core.XWalkView;
 import org.xwalk.core.XWalkClient;
index dad8540..d26e82f 100644 (file)
@@ -8,10 +8,9 @@ package org.xwalk.core.xwview.test;
 import android.graphics.Bitmap;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
+
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.xwalk.core.XWalkView;
-import org.xwalk.core.XWalkClient;
 
 /**
  * Test suite for loadUrl().
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/NullContentsClient.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/NullContentsClient.java
deleted file mode 100644 (file)
index b5ffedf..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-// 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.xwalk.core.xwview.test;
-
-import android.graphics.Bitmap;
-import android.graphics.Picture;
-import android.net.http.SslError;
-import android.os.Message;
-import android.view.KeyEvent;
-import android.view.View;
-import android.webkit.ConsoleMessage;
-import android.webkit.ValueCallback;
-import android.webkit.WebResourceResponse;
-
-import org.xwalk.core.XWalkJavascriptResult;
-import org.xwalk.core.XWalkJavascriptResult;
-import org.xwalk.core.XWalkContentsClient;
-import org.xwalk.core.XWalkGeolocationPermissions;
-import org.xwalk.core.XWalkHttpAuthHandler;
-import org.xwalk.core.XWalkWebChromeClient;
-
-/**
- * As a convience for tests that only care about specefic callbacks, this class provides
- * empty implementations of all abstract methods.
- */
-public class NullContentsClient extends XWalkContentsClient {
-    @Override
-    public void onUnhandledKeyEvent(KeyEvent event) {
-    }
-
-    @Override
-    public void getVisitedHistory(ValueCallback<String[]> callback) {
-    }
-
-    @Override
-    public void doUpdateVisitedHistory(String url, boolean isReload) {
-    }
-
-    @Override
-    public void onProgressChanged(int progress) {
-    }
-
-    @Override
-    public WebResourceResponse shouldInterceptRequest(String url) {
-        return null;
-    }
-
-    @Override
-    public void onLoadResource(String url) {
-    }
-
-    @Override
-    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
-        return false;
-    }
-
-    @Override
-    public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) {
-    }
-
-    @Override
-    public void onReceivedLoginRequest(String realm, String account, String args) {
-    }
-
-    @Override
-    public void onGeolocationPermissionsShowPrompt(String origin,
-            XWalkGeolocationPermissions.Callback callback) {
-    }
-
-    @Override
-    public void onGeolocationPermissionsHidePrompt() {
-    }
-
-
-    @Override
-    public boolean hasEnteredFullscreen() {
-        return false;
-    }
-
-    @Override
-    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
-            boolean isDoneCounting) {
-    }
-
-    @Override
-    public void onNewPicture(Picture picture) {
-    }
-
-    @Override
-    public void onPageStarted(String url) {
-    }
-
-    @Override
-    public void onPageFinished(String url) {
-    }
-
-    @Override
-    public void onReceivedError(int errorCode, String description, String failingUrl) {
-    }
-
-    @Override
-    public void onFormResubmission(Message dontResend, Message resend) {
-        dontResend.sendToTarget();
-    }
-
-    @Override
-    public void onDownloadStart(String url,
-                                String userAgent,
-                                String contentDisposition,
-                                String mimeType,
-                                long contentLength) {
-    }
-
-    @Override
-    public boolean onCreateWindow(boolean isDialog, boolean isUserGesture) {
-        return false;
-    }
-
-    @Override
-    public void onCloseWindow() {
-    }
-
-    @Override
-    public void onRequestFocus() {
-    }
-
-    @Override
-    public void onReceivedTouchIconUrl(String url, boolean precomposed) {
-    }
-
-    @Override
-    public void onReceivedIcon(Bitmap bitmap) {
-    }
-
-    @Override
-    public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
-    }
-
-    @Override
-    public void onHideCustomView() {
-    }
-
-    @Override
-    public void onScaleChangedScaled(float oldScale, float newScale) {
-    }
-
-    @Override
-    protected View getVideoLoadingProgressView() {
-        return null;
-    }
-
-    @Override
-    public Bitmap getDefaultVideoPoster() {
-        return null;
-    }
-
-    @Override
-    public void didFinishLoad(String url) {
-    }
-
-    @Override
-    public void onReceivedHttpAuthRequest(XWalkHttpAuthHandler handler, String host, String realm) {
-    }
-
-    @Override
-    public boolean shouldOverrideUrlLoading(String url) {
-        return false;
-    }
-
-    @Override
-    public void onTitleChanged(String title) {
-    }
-
-    @Override
-    public void onToggleFullscreen(boolean enterFullscreen) {
-    }
-
-    @Override
-    public void onRendererResponsive() {
-    }
-
-    @Override
-    public void onRendererUnresponsive() {
-    }
-}
index e5528e6..019d867 100644 (file)
@@ -13,7 +13,6 @@ import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.net.test.util.TestWebServer;
 
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
 import org.xwalk.core.XWalkView;
 
 import java.util.concurrent.TimeUnit;
@@ -40,10 +39,10 @@ public class OnPageFinishedTest extends XWalkViewTestBase {
 
         String html = "<html><body>Simple page.</body></html>";
         int currentCallCount = onPageFinishedHelper.getCallCount();
-        loadDataAsync(html, "text/html", false);
+        loadDataAsync(null, html, "text/html", false);
 
         onPageFinishedHelper.waitForCallback(currentCallCount);
-        assertEquals("data:text/html," + html, onPageFinishedHelper.getUrl());
+        assertEquals("about:blank", onPageFinishedHelper.getUrl());
     }
 
     @MediumTest
@@ -91,7 +90,7 @@ public class OnPageFinishedTest extends XWalkViewTestBase {
 
             assertEquals(0, onPageFinishedHelper.getCallCount());
             final int pageWithSubresourcesCallCount = onPageFinishedHelper.getCallCount();
-            loadDataAsync("<html><iframe src=\"" + testUrl + "\" /></html>",
+            loadDataAsync(null, "<html><iframe src=\"" + testUrl + "\" /></html>",
                           "text/html",
                           false);
 
@@ -122,11 +121,11 @@ public class OnPageFinishedTest extends XWalkViewTestBase {
         int currentCallCount = onPageFinishedHelper.getCallCount();
         assertEquals(0, currentCallCount);
 
-        loadDataAsync(html, "text/html", false);
+        loadDataAsync(null, html, "text/html", false);
         loadJavaScriptUrl("javascript: try { console.log('foo'); } catch(e) {};");
 
         onPageFinishedHelper.waitForCallback(currentCallCount);
-        assertEquals("data:text/html," + html, onPageFinishedHelper.getUrl());
+        assertEquals("about:blank", onPageFinishedHelper.getUrl());
         // onPageFinished won't be called for javascript: url.
         assertEquals(1, onPageFinishedHelper.getCallCount());
     }
index 39a2b22..f07f076 100644 (file)
@@ -51,7 +51,7 @@ public class ReloadTest extends XWalkViewTestBase {
         String url = mWebServer.setResponse("/reload.html", html1, null);
         loadUrlSync(url);
         mWebServer.setResponse("/reload.html", html2, null);
-        reloadSync();
+        reloadSync(XWalkView.RELOAD_IGNORE_CACHE);
         //TODO(guangzhen) When reload finished, immediately call getTitle will get wrong title.
         Thread.sleep(1000);
         assertEquals(title2, getTitleOnUiThread());
index 760d4a5..1ebc5c1 100644 (file)
@@ -20,7 +20,6 @@ import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.ContentViewCore;
 
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
 import org.xwalk.core.XWalkView;
 
 /**
@@ -45,8 +44,7 @@ public class RendererResponsivenessTest extends XWalkViewTestBase {
     @DisabledTest
     public void testRendererUnresponsive() throws Throwable {
         setXWalkClient(new XWalkViewTestBase.TestXWalkClient());
-        getXWalkView().setXWalkClient(new XWalkClient(getXWalkView().getContext(),
-                    getXWalkView()) {
+        getXWalkView().setXWalkClient(new XWalkClient(getXWalkView()) {
             @Override
             public void onRendererUnresponsive(XWalkView view) {
                 unresponsiveHelper.notifyCalled(view);
@@ -56,9 +54,7 @@ public class RendererResponsivenessTest extends XWalkViewTestBase {
         loadAssetFile("renderHung.html");
 
         int currentCallCount = unresponsiveHelper.getCallCount();
-
-        XWalkContent content = getXWalkView().getXWalkViewContentForTest();
-        content.getContentViewCoreForTest().evaluateJavaScript("deadLoopForever();", null);
+        getXWalkView().evaluateJavascript("deadLoopForever();", null);
 
         /**
          * Send an input event to xwalk view. Internally, if no ACK message is received
@@ -81,8 +77,7 @@ public class RendererResponsivenessTest extends XWalkViewTestBase {
     @DisabledTest
     public void testRendererResponsiveAgain() throws Throwable {
         setXWalkClient(new XWalkViewTestBase.TestXWalkClient());
-        getXWalkView().setXWalkClient(new XWalkClient(getXWalkView().getContext(),
-                    getXWalkView()) {
+        getXWalkView().setXWalkClient(new XWalkClient(getXWalkView()) {
             /**
              * Called once the renderer become responsive again.
              */
@@ -95,8 +90,7 @@ public class RendererResponsivenessTest extends XWalkViewTestBase {
         loadAssetFile("renderHung.html");
 
         int currentCallCount = responsiveHelper.getCallCount();
-        XWalkContent content = getXWalkView().getXWalkViewContentForTest();
-        content.getContentViewCoreForTest().evaluateJavaScript("deadLoopFor40secs();", null);
+        getXWalkView().evaluateJavascript("deadLoopFor40secs();", null);
 
         /**
          * Send an input event to start the hung monitor.
index 5050b4c..3212860 100644 (file)
@@ -16,10 +16,11 @@ import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.NavigationEntry;
 import org.chromium.content.browser.NavigationHistory;
 import org.chromium.net.test.util.TestWebServer;
-import org.xwalk.core.xwview.test.util.CommonResources;
+
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
+import org.xwalk.core.XWalkNavigationHistory;
 import org.xwalk.core.XWalkView;
+import org.xwalk.core.xwview.test.util.CommonResources;
 
 import java.util.concurrent.Callable;
 
@@ -42,7 +43,6 @@ public class SaveRestoreStateTest extends XWalkViewTestBase {
     private String mUrls[];
     private XWalkView mXWalkView;
     private XWalkView mRestoreXWalkView;
-    private XWalkContent mXWalkContent;
 
     @Override
     public void setUp() throws Exception {
@@ -55,7 +55,6 @@ public class SaveRestoreStateTest extends XWalkViewTestBase {
                 mXWalkView = getXWalkView();
                 mRestoreXWalkView = new XWalkView(activity, activity);
                 mXWalkView.setXWalkClient(new XWalkViewTestBase.TestXWalkClient());
-                mXWalkContent = mXWalkView.getXWalkViewContentForTest();
             }
         });
 
@@ -81,28 +80,28 @@ public class SaveRestoreStateTest extends XWalkViewTestBase {
         }
     }
 
-    private NavigationHistory getNavigationHistoryOnUiThread(
-            final XWalkContent content) throws Throwable{
-        return runTestOnUiThreadAndGetResult(new Callable<NavigationHistory>() {
+    private XWalkNavigationHistory getNavigationHistoryOnUiThread(
+            final XWalkView content) throws Throwable{
+        return runTestOnUiThreadAndGetResult(new Callable<XWalkNavigationHistory>() {
             @Override
-            public NavigationHistory call() throws Exception {
-                return content.getContentViewCoreForTest().getNavigationHistory();
+            public XWalkNavigationHistory call() throws Exception {
+                return content.getNavigationHistory();
             }
         });
     }
 
-    private void checkHistoryItemList(XWalkContent content) throws Throwable {
-        NavigationHistory history = getNavigationHistoryOnUiThread(content);
-        assertEquals(NUM_NAVIGATIONS, history.getEntryCount());
-        assertEquals(NUM_NAVIGATIONS - 1, history.getCurrentEntryIndex());
+    private void checkHistoryItemList(XWalkView content) throws Throwable {
+        XWalkNavigationHistory history = getNavigationHistoryOnUiThread(content);
+        assertEquals(NUM_NAVIGATIONS, history.size());
+        assertEquals(NUM_NAVIGATIONS - 1, history.getCurrentIndex());
 
         // Note this is not meant to be a thorough test of NavigationHistory,
         // but is only meant to test enough to make sure state is restored.
         // See NavigationHistoryTest for more thorough tests.
         for (int i = 0; i < NUM_NAVIGATIONS; ++i) {
-            assertEquals(mUrls[i], history.getEntryAtIndex(i).getOriginalUrl());
-            assertEquals(mUrls[i], history.getEntryAtIndex(i).getUrl());
-            assertEquals(TITLES[i], history.getEntryAtIndex(i).getTitle());
+            assertEquals(mUrls[i], history.getItemAt(i).getOriginalUrl());
+            assertEquals(mUrls[i], history.getItemAt(i).getUrl());
+            assertEquals(TITLES[i], history.getItemAt(i).getTitle());
         }
     }
 
@@ -126,7 +125,7 @@ public class SaveRestoreStateTest extends XWalkViewTestBase {
             @Override
             public Boolean call() throws Exception {
                 // TODO(hengzhi): add the judge about updated title.
-                return TITLES[0].equals(mXWalkContent.getContentViewCoreForTest().getTitle());
+                return TITLES[0].equals(mXWalkView.getTitle());
             }
         }));
     }
@@ -137,14 +136,16 @@ public class SaveRestoreStateTest extends XWalkViewTestBase {
     public void testSaveRestoreStateWithHistoryItemList() throws Throwable {
         setServerResponseAndLoad(NUM_NAVIGATIONS);
         saveAndRestoreStateOnUiThread();
-        checkHistoryItemList(mRestoreXWalkView.getXWalkViewContentForTest());
+        checkHistoryItemList(mRestoreXWalkView);
     }
 
     @SmallTest
     @Feature({"SaveRestoreState"})
     public void testRestoreFromInvalidStateFails() throws Throwable {
         final Bundle invalidState = new Bundle();
-        invalidState.putByteArray(mXWalkContent.SAVE_RESTORE_STATE_KEY,
+        // TODO(yongsheng): how to share this with
+        // XWalkContent.SAVE_RESTORE_STATE_KEY?
+        invalidState.putByteArray("XWALKVIEW_STATE",
                                   "invalid state".getBytes());
         boolean result = runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
             @Override
index e262a7f..fa25a46 100644 (file)
@@ -21,7 +21,6 @@ import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.net.test.util.TestWebServer;
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
 import org.xwalk.core.XWalkSettings;
 import org.xwalk.core.XWalkView;
 import org.xwalk.core.XWalkWebChromeClient;
@@ -114,7 +113,6 @@ public class SetAppCacheEnabledTest extends XWalkViewTestBase {
                 createXWalkViewContainerOnMainSync(getActivity(), client,
                         resourceClient, chromeClient);
 
-        final XWalkContent xWalkContent = getXWalkContentOnMainSync(xWalkView);
         final XWalkSettings settings = getXWalkSettings(xWalkView);
         settings.setJavaScriptEnabled(true);
         settings.setAppCacheEnabled(false);
@@ -125,7 +123,7 @@ public class SetAppCacheEnabledTest extends XWalkViewTestBase {
             ManifestTestHelper helper = new ManifestTestHelper(
                     webServer, "testAppCache.html", "appcache.manifest");
             loadUrlSyncByContent(
-                    xWalkContent,
+                    xWalkView,
                     mContentClient,
                     helper.getHtmlUrl());
             helper.waitUntilHtmlIsRequested(0);
@@ -136,7 +134,7 @@ public class SetAppCacheEnabledTest extends XWalkViewTestBase {
             // Enables AppCache. Use the default path if app cache path isn't set.
             settings.setAppCacheEnabled(true);
             loadUrlSyncByContent(
-                    xWalkContent,
+                    xWalkView,
                     mContentClient,
                     helper.getHtmlUrl());
             helper.waitUntilManifestIsRequested(0);
index cd27d86..964f040 100644 (file)
@@ -14,7 +14,6 @@ import java.util.concurrent.atomic.AtomicReference;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
 import org.xwalk.core.XWalkSettings;
 import org.xwalk.core.XWalkView;
 import org.xwalk.core.XWalkWebChromeClient;
@@ -27,12 +26,12 @@ public class SetDomStorageEnabledTest extends XWalkViewTestBase {
     private static final boolean DISABLED = false;
 
     abstract class XWalkViewSettingsTestHelper<T> {
-        protected final XWalkContent mXWalkContent;
+        protected final XWalkView mXWalkView;
         protected final XWalkSettings mXWalkSettings;
 
-        XWalkViewSettingsTestHelper(XWalkContent xWalkContent,
+        XWalkViewSettingsTestHelper(XWalkView xWalkContent,
                 boolean requiresJsEnabled) throws Throwable {
-            mXWalkContent = xWalkContent;
+            mXWalkView = xWalkContent;
             mXWalkSettings = getXWalkSettingsOnUiThreadByContent(xWalkContent);
             mXWalkSettings.setDomStorageEnabled(false);
             if (requiresJsEnabled) {
@@ -78,7 +77,7 @@ public class SetDomStorageEnabledTest extends XWalkViewTestBase {
         TestHelperBridge mHelperBridge;
 
         XWalkViewSettingsDomStorageEnabledTestHelper(
-                XWalkContent xWalkContent,
+                XWalkView xWalkContent,
                 final TestHelperBridge helperBridge) throws Throwable {
             super(xWalkContent, true);
             mHelperBridge = helperBridge;
@@ -108,7 +107,7 @@ public class SetDomStorageEnabledTest extends XWalkViewTestBase {
         protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
             // It is not permitted to access localStorage from data URLs in WebKit,
             // that is why a standalone page must be used.
-            loadUrlSyncByContent(mXWalkContent, mHelperBridge,
+            loadUrlSyncByContent(mXWalkView, mHelperBridge,
                     UrlUtils.getTestFileUrl("xwalkview/localStorage.html"));
             assertEquals(
                 value == ENABLED ? HAS_LOCAL_STORAGE : NO_LOCAL_STORAGE,
index 294246d..eb72a91 100644 (file)
@@ -12,7 +12,6 @@ import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
 import org.xwalk.core.XWalkView;
 
 /**
index 8e559a7..e73369a 100644 (file)
@@ -23,9 +23,9 @@ import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
 import org.chromium.net.test.util.TestWebServer;
 
-import org.xwalk.core.xwview.test.util.CommonResources;
 import org.xwalk.core.XWalkView;
-import org.xwalk.core.XWalkResourceClient;
+import org.xwalk.core.xwview.test.TestContentProvider;
+import org.xwalk.core.xwview.test.util.CommonResources;
 
 /**
  * Test case for XWalkResourceClient.shouldInterceptRequest callback
index 2dc8555..4603a78 100644 (file)
@@ -6,6 +6,7 @@
 package org.xwalk.core.xwview.test;
 
 import android.util.Log;
+import android.webkit.ValueCallback;
 import android.webkit.WebResourceResponse;
 
 import java.util.ArrayList;
@@ -13,13 +14,16 @@ import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeoutException;
 
 import org.chromium.content.browser.test.util.CallbackHelper;
-import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
+import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
 
+import org.xwalk.core.XWalkView;
+
 class TestHelperBridge {
 
     // Two new helper classes for testing new APIs.
@@ -76,12 +80,57 @@ class TestHelperBridge {
         }
     }
 
+    class OnEvaluateJavaScriptResultHelper extends CallbackHelper {
+        private String mJsonResult;
+        public void evaluateJavascript(XWalkView xWalkView, String code) {
+            ValueCallback<String> callback =
+                new ValueCallback<String>() {
+                    @Override
+                    public void onReceiveValue(String jsonResult) {
+                        notifyCalled(jsonResult);
+                    }
+                };
+            xWalkView.evaluateJavascript(code, callback);
+            mJsonResult = null;
+        }
+
+        public boolean hasValue() {
+            return mJsonResult != null;
+        }
+
+        public boolean waitUntilHasValue() throws InterruptedException, TimeoutException {
+            waitUntilCriteria(getHasValueCriteria());
+            return hasValue();
+        }
+
+        public String getJsonResultAndClear() {
+            assert hasValue();
+            String result = mJsonResult;
+            mJsonResult = null;
+            return result;
+        }
+
+        public Criteria getHasValueCriteria() {
+            return new Criteria() {
+                @Override
+                public boolean isSatisfied() {
+                    return hasValue();
+                }
+            };
+        }
+
+        public void notifyCalled(String jsonResult) {
+            assert !hasValue();
+            mJsonResult = jsonResult;
+            notifyCalled();
+        }
+    }
+
     private String mChangedTitle;
     private final OnPageStartedHelper mOnPageStartedHelper;
     private final OnPageFinishedHelper mOnPageFinishedHelper;
     private final OnReceivedErrorHelper mOnReceivedErrorHelper;
 
-    // TODO(yongsheng): write test for this.
     private final OnEvaluateJavaScriptResultHelper mOnEvaluateJavaScriptResultHelper;
 
     private final OnTitleUpdatedHelper mOnTitleUpdatedHelper;
index 87557ee..ae86065 100644 (file)
@@ -17,7 +17,6 @@ import org.apache.http.HttpRequest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.net.test.util.TestWebServer;
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
 import org.xwalk.core.XWalkSettings;
 import org.xwalk.core.XWalkView;
 
@@ -37,7 +36,7 @@ public class UserAgentTest extends XWalkViewTestBase {
         return runTestOnUiThreadAndGetResult(new Callable<XWalkSettings>() {
             @Override
             public XWalkSettings call() throws Exception {
-                return getXWalkView().getXWalkViewContentForTest().getSettings();
+                return getXWalkView().getSettings();
             }
         });
     }
index 8a7e6db..8e1cfd6 100644 (file)
@@ -24,13 +24,9 @@ import org.chromium.content.browser.LoadUrlParams;
 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.OnEvaluateJavaScriptResultHelper;
 import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkContent;
-import org.xwalk.core.XWalkContentsClient;
 import org.xwalk.core.XWalkNavigationHistory;
 import org.xwalk.core.XWalkResourceClient;
-import org.xwalk.core.XWalkResourceClientImpl;
 import org.xwalk.core.XWalkSettings;
 import org.xwalk.core.XWalkView;
 import org.xwalk.core.XWalkWebChromeClient;
@@ -45,7 +41,7 @@ public class XWalkViewTestBase
     class TestXWalkClientBase extends XWalkClient {
         TestHelperBridge mInnerContentsClient;
         public TestXWalkClientBase(TestHelperBridge client) {
-            super(getXWalkView().getContext(), getXWalkView());
+            super(getXWalkView());
             mInnerContentsClient = client;
         }
 
@@ -69,7 +65,7 @@ public class XWalkViewTestBase
     class TestXWalkWebChromeClientBase extends XWalkWebChromeClient {
         TestHelperBridge mInnerContentsClient;
         public TestXWalkWebChromeClientBase(TestHelperBridge client) {
-            super(getXWalkView().getContext(), getXWalkView());
+            super(getXWalkView());
             mInnerContentsClient = client;
         }
 
@@ -88,6 +84,7 @@ public class XWalkViewTestBase
     class TestXWalkResourceClientBase extends XWalkResourceClient {
         TestHelperBridge mInnerContentsClient;
         public TestXWalkResourceClientBase(TestHelperBridge client) {
+            super(mXWalkView);
             mInnerContentsClient = client;
         }
 
@@ -142,20 +139,20 @@ public class XWalkViewTestBase
     }
 
     static class ViewPair {
-        private final XWalkContent content0;
+        private final XWalkView content0;
         private final TestHelperBridge client0;
-        private final XWalkContent content1;
+        private final XWalkView content1;
         private final TestHelperBridge client1;
 
-        ViewPair(XWalkContent content0, TestHelperBridge client0,
-                XWalkContent content1, TestHelperBridge client1) {
+        ViewPair(XWalkView content0, TestHelperBridge client0,
+                XWalkView content1, TestHelperBridge client1) {
             this.content0 = content0;
             this.client0 = client0;
             this.content1 = content1;
             this.client1 = client1;
         }
 
-        XWalkContent getContent0() {
+        XWalkView getContent0() {
             return content0;
         }
 
@@ -163,7 +160,7 @@ public class XWalkViewTestBase
             return client0;
         }
 
-        XWalkContent getContent1() {
+        XWalkView getContent1() {
             return content1;
         }
 
@@ -231,28 +228,26 @@ public class XWalkViewTestBase
         });
     }
 
-    protected void loadDataSync(final String data, final String mimeType,
+    protected void loadDataSync(final String url, final String data, final String mimeType,
             final boolean isBase64Encoded) throws Exception {
         CallbackHelper pageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
         int currentCallCount = pageFinishedHelper.getCallCount();
-        loadDataAsync(data, mimeType, isBase64Encoded);
+        loadDataAsync(url, data, mimeType, isBase64Encoded);
         pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
                 TimeUnit.SECONDS);
     }
 
-    protected void loadDataAsync(final String data, final String mimeType,
+    protected void loadDataAsync(final String url, final String data, final String mimeType,
              final boolean isBase64Encoded) throws Exception {
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
-                mXWalkView.getXWalkViewContentForTest().getContentViewCoreForTest(
-                        ).loadUrl(LoadUrlParams.createLoadDataParams(
-                        data, mimeType, isBase64Encoded));
+                mXWalkView.load(url, data);
             }
         });
     }
 
-    protected void loadUrlSyncByContent(final XWalkContent xWalkContent,
+    protected void loadUrlSyncByContent(final XWalkView xWalkContent,
             final TestHelperBridge contentsClient,
             final String url) throws Exception {
         CallbackHelper pageFinishedHelper = contentsClient.getOnPageFinishedHelper();
@@ -263,12 +258,12 @@ public class XWalkViewTestBase
                 TimeUnit.SECONDS);
     }
 
-    protected void loadUrlAsyncByContent(final XWalkContent xWalkContent,
+    protected void loadUrlAsyncByContent(final XWalkView xWalkContent,
             final String url) throws Exception {
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
-                xWalkContent.loadUrl(url);
+                xWalkContent.load(url, null);
             }
         });
     }
@@ -306,18 +301,18 @@ public class XWalkViewTestBase
         }
     }
 
-    protected String getTitleOnUiThreadByContent(final XWalkContent xWalkContent) throws Exception {
+    protected String getTitleOnUiThreadByContent(final XWalkView xWalkContent) throws Exception {
         return runTestOnUiThreadAndGetResult(new Callable<String>() {
             @Override
             public String call() throws Exception {
-                String title = xWalkContent.getContentViewCoreForTest().getTitle();
+                String title = xWalkContent.getTitle();
                 return title;
             }
         });
     }
 
     protected XWalkSettings getXWalkSettingsOnUiThreadByContent(
-            final XWalkContent xwalkContent) throws Exception {
+            final XWalkView xwalkContent) throws Exception {
         return runTestOnUiThreadAndGetResult(new Callable<XWalkSettings>() {
             @Override
             public XWalkSettings call() throws Exception {
@@ -347,19 +342,6 @@ public class XWalkViewTestBase
         return xWalkViewContainer.get();
     }
 
-    protected XWalkContent getXWalkContentOnMainSync(final XWalkView view) throws Exception {
-        final AtomicReference<XWalkContent> xWalkContent =
-                new AtomicReference<XWalkContent>();
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                xWalkContent.set(view.getXWalkViewContentForTest());
-            }
-        });
-
-        return xWalkContent.get();
-    }
-
     protected ViewPair createViewsOnMainSync(final TestHelperBridge helperBridge0,
                                              final TestHelperBridge helperBridge1,
                                              final XWalkClient client0,
@@ -378,9 +360,7 @@ public class XWalkViewTestBase
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
-                XWalkContent content0 = walkView0.getXWalkViewContentForTest();
-                XWalkContent content1 = walkView1.getXWalkViewContentForTest();
-                viewPair.set(new ViewPair(content0, helperBridge0, content1, helperBridge1));
+                viewPair.set(new ViewPair(walkView0, helperBridge0, walkView1, helperBridge1));
             }
         });
 
@@ -389,7 +369,7 @@ public class XWalkViewTestBase
 
     protected void loadAssetFile(String fileName) throws Exception {
         String fileContent = getFileContent(fileName);
-        loadDataSync(fileContent, "text/html", false);
+        loadDataSync(fileName, fileContent, "text/html", false);
     }
 
     public void loadAssetFileAndWaitForTitle(String fileName) throws Exception {
@@ -397,7 +377,7 @@ public class XWalkViewTestBase
         int currentCallCount = getTitleHelper.getCallCount();
         String fileContent = getFileContent(fileName);
 
-        loadDataSync(fileContent, "text/html", false);
+        loadDataSync(fileName, fileContent, "text/html", false);
 
         getTitleHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
                 TimeUnit.SECONDS);
@@ -415,14 +395,14 @@ public class XWalkViewTestBase
                 TimeUnit.SECONDS);
     }
 
-    protected void reloadSync() throws Exception {
+    protected void reloadSync(final int mode) throws Exception {
         runTestWaitPageFinished(new Runnable(){
             @Override
             public void run() {
                 getInstrumentation().runOnMainSync(new Runnable() {
                     @Override
                     public void run() {
-                        mXWalkView.reload();
+                        mXWalkView.reload(mode);
                     }
                 });
             }
@@ -487,13 +467,13 @@ public class XWalkViewTestBase
     }
 
     protected String executeJavaScriptAndWaitForResult(final String code) throws Exception {
-        final OnEvaluateJavaScriptResultHelper helper =
+
+        final TestHelperBridge.OnEvaluateJavaScriptResultHelper helper =
                 mTestHelperBridge.getOnEvaluateJavaScriptResultHelper();
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
-                XWalkContent content = mXWalkView.getXWalkViewContentForTest();
-                helper.evaluateJavaScript(content.getContentViewCoreForTest(), code);
+                helper.evaluateJavascript(mXWalkView, code);
             }
         });
         helper.waitUntilHasValue();
diff --git a/src/xwalk/test/android/data/www/cross_origin.html b/src/xwalk/test/android/data/www/cross_origin.html
new file mode 100644 (file)
index 0000000..eb724c6
--- /dev/null
@@ -0,0 +1,21 @@
+<html>
+<head>
+<title>Original Title</title>
+<script>
+window.onload = function() {
+  var xhr = new XMLHttpRequest();
+  xhr.onreadystatechange = function() {
+    if (xhr.readyState==4 && xhr.status==200) {
+      // The response text from test server should be "Cross-Origin XHR".
+      document.title = xhr.responseText;
+    }
+  };
+  xhr.open("GET", 'http://localhost:4444/cross_origin_xhr_test.html', true);
+  xhr.send();
+}
+</script>
+</head>
+<body>
+<h1>Test Page for Cross-Origin XHR.</hi>
+</body>
+</html>
diff --git a/src/xwalk/test/android/data/www/manifest_without_xwalk_hosts.json b/src/xwalk/test/android/data/www/manifest_without_xwalk_hosts.json
new file mode 100644 (file)
index 0000000..692fae5
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "name": "Cross Origin XHR Test",
+  "version": "1.0.0",
+  "description": "Test for Cross-Origin XHR without xwalk_hosts",
+  "app": {
+    "launch": {
+      "local_path": "cross_origin.html"
+    }
+  }
+}
diff --git a/src/xwalk/test/android/data/www/manifest_xwalk_hosts.json b/src/xwalk/test/android/data/www/manifest_xwalk_hosts.json
new file mode 100644 (file)
index 0000000..c7a64e2
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  "name": "Cross Origin XHR Test",
+  "version": "1.0.0",
+  "description": "Test for Cross-Origin XHR",
+  "app": {
+    "launch": {
+      "local_path": "cross_origin.html"
+    }
+  },
+  "xwalk_hosts": [
+    "http://localhost:4444/*"
+  ]
+}
index 27f6702..570fa3f 100644 (file)
@@ -21,6 +21,7 @@
     <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.READ_LOGS"/>
     <uses-permission android:name="android.permission.WAKE_LOCK" />
 </manifest>
index f8f6836..af3faf6 100644 (file)
@@ -21,6 +21,7 @@
     <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.READ_CONTACTS"/>
     <uses-permission android:name="android.permission.READ_LOGS"/>
     <uses-permission android:name="android.permission.WAKE_LOCK" />
diff --git a/src/xwalk/test/android/runtime_client/javatests/src/org/xwalk/runtime/client/test/CrossOriginXhrTest.java b/src/xwalk/test/android/runtime_client/javatests/src/org/xwalk/runtime/client/test/CrossOriginXhrTest.java
new file mode 100644 (file)
index 0000000..93639a8
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 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.
+
+package org.xwalk.runtime.client.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import org.chromium.base.test.util.Feature;
+import org.xwalk.runtime.client.shell.XWalkRuntimeClientShellActivity;
+import org.xwalk.test.util.RuntimeClientApiTestBase;
+
+/**
+ * Test suite for CrossOriginXhr.
+ */
+public class CrossOriginXhrTest extends XWalkRuntimeClientTestBase {
+
+    @SmallTest
+    @Feature({"CrossOriginXhr"})
+    public void testCrossOriginXhr() throws Throwable {
+        RuntimeClientApiTestBase<XWalkRuntimeClientShellActivity> helper =
+                new RuntimeClientApiTestBase<XWalkRuntimeClientShellActivity>(
+                        getTestUtil(), this);
+        helper.testCrossOriginXhr();
+    }
+}
index dca0ae9..8da0735 100644 (file)
@@ -21,6 +21,7 @@
     <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.READ_CONTACTS"/>
     <uses-permission android:name="android.permission.READ_LOGS"/>
     <uses-permission android:name="android.permission.WAKE_LOCK" />
diff --git a/src/xwalk/test/android/runtime_client_embedded/javatests/src/org/xwalk/runtime/client/embedded/test/CrossOriginXhrTest.java b/src/xwalk/test/android/runtime_client_embedded/javatests/src/org/xwalk/runtime/client/embedded/test/CrossOriginXhrTest.java
new file mode 100644 (file)
index 0000000..3c8e019
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 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.
+
+package org.xwalk.runtime.client.embedded.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import org.chromium.base.test.util.Feature;
+import org.xwalk.runtime.client.embedded.shell.XWalkRuntimeClientEmbeddedShellActivity;
+import org.xwalk.test.util.RuntimeClientApiTestBase;
+
+/**
+ * Test suite for CrossOriginXhr.
+ */
+public class CrossOriginXhrTest extends XWalkRuntimeClientTestBase {
+
+    @SmallTest
+    @Feature({"CrossOriginXhr"})
+    public void testCrossOriginXhr() throws Throwable {
+        RuntimeClientApiTestBase<XWalkRuntimeClientEmbeddedShellActivity> helper =
+                new RuntimeClientApiTestBase<XWalkRuntimeClientEmbeddedShellActivity>(
+                        getTestUtil(), this);
+        helper.testCrossOriginXhr();
+    }
+}
index c27b828..607ac69 100644 (file)
@@ -24,6 +24,7 @@ import java.util.TimerTask;
 
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
+import org.chromium.net.test.util.TestWebServer;
 /**
  * Test helper for Runtime client APIs.
  */
@@ -168,7 +169,7 @@ public class RuntimeClientApiTestBase<T extends Activity> {
         });
     }
 
-   // For testCSP.
+    // For testCSP.
     public void testCSP() throws Throwable {
         final String originalTitle = "Original Title";
         final String newTitle = "New Title";
@@ -212,6 +213,70 @@ public class RuntimeClientApiTestBase<T extends Activity> {
         });
     }
 
+    // For Cross-Origin XHR.
+    public void testCrossOriginXhr() throws Throwable {
+        TestWebServer webServer = null;
+        try {
+            // The server will be accessed by XMLHttpRequest from js.
+            webServer = new TestWebServer(false);
+            final String path = "/cross_origin_xhr_test.html";
+            final String responseStr = "Cross-Origin XHR";
+            final String url = webServer.setResponse(path, responseStr, null);
+            mTestCase.assertEquals("http://localhost:4444/cross_origin_xhr_test.html", url);
+
+            // The original title of the cross_origin.html.
+            final String originalTitle = "Original Title";
+
+            // Test without the xwalk_hosts member.
+            mTestUtil.loadManifestSync("file:///android_asset/www/manifest_without_xwalk_hosts.json");
+            Thread.sleep(1000);
+            mTestCase.getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    String title = mTestUtil.getTestedView().getTitleForTest();
+                    // XHR in page should be failed, and the title should be "Original Title".
+                    mTestCase.assertEquals(originalTitle, title);
+                }
+            });
+
+            // Test with the manifest which has a xwalk_host member.
+            mTestUtil.loadManifestSync("file:///android_asset/www/manifest_xwalk_hosts.json");
+            Thread.sleep(1000);
+            mTestCase.getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    String title = mTestUtil.getTestedView().getTitleForTest();
+                    // XHR in page should be success, and the title should be "Cross-Origin XHR".
+                    mTestCase.assertEquals(responseStr, title);
+                }
+            });
+
+            // Retry with app:// scheme.
+            final String host = mTestCase.getActivity().getPackageName();
+            mTestUtil.loadManifestSync("app://" + host + "/manifest_without_xwalk_hosts.json");
+            Thread.sleep(1000);
+            mTestCase.getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    String title = mTestUtil.getTestedView().getTitleForTest();
+                    mTestCase.assertEquals(originalTitle, title);
+                }
+            });
+
+            mTestUtil.loadManifestSync("app://" + host + "/manifest_xwalk_hosts.json");
+            Thread.sleep(1000);
+            mTestCase.getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    String title = mTestUtil.getTestedView().getTitleForTest();
+                    mTestCase.assertEquals(responseStr, title);
+                }
+            });
+        } finally {
+            if (webServer != null) webServer.shutdown();
+        }
+    }
+
     // For internal extension implementation of Contacts.
     public void testContacts() throws Throwable {
         String title = mTestUtil.loadAssetFileAndWaitForTitle("contacts.html");
index ba972b5..8402285 100644 (file)
         '..',
       ],
       'sources': [
+        '../extensions/common/constants.cc',
+        '../extensions/common/constants.h',
+        '../extensions/common/url_pattern.cc',
+        '../extensions/common/url_pattern.h',
         'runtime/app/android/xwalk_main_delegate_android.cc',
         'runtime/app/android/xwalk_main_delegate_android.h',
         'runtime/app/xwalk_main_delegate.cc',
         'runtime/browser/android/xwalk_request_interceptor.cc',
         'runtime/browser/android/xwalk_request_interceptor.h',
         'runtime/browser/android/xwalk_settings.cc',
+        'runtime/browser/android/xwalk_view_delegate.cc',
+        'runtime/browser/android/xwalk_view_delegate.h',
         'runtime/browser/android/xwalk_web_contents_delegate.cc',
         'runtime/browser/android/xwalk_web_contents_delegate.h',
         'runtime/browser/android/xwalk_web_contents_view_delegate.cc',
         'runtime/common/xwalk_common_message_generator.h',
         'runtime/common/xwalk_content_client.cc',
         'runtime/common/xwalk_content_client.h',
+        'runtime/common/xwalk_localized_error.cc',
+        'runtime/common/xwalk_localized_error.h',
         'runtime/common/xwalk_paths.cc',
         'runtime/common/xwalk_paths.h',
         'runtime/common/xwalk_runtime_features.cc',
         'runtime/renderer/android/xwalk_render_view_ext.h',
         'runtime/renderer/tizen/xwalk_content_renderer_client_tizen.cc',
         'runtime/renderer/tizen/xwalk_content_renderer_client_tizen.h',
+        'runtime/renderer/tizen/xwalk_render_view_ext_tizen.cc',
+        'runtime/renderer/tizen/xwalk_render_view_ext_tizen.h',
         'runtime/renderer/xwalk_content_renderer_client.cc',
         'runtime/renderer/xwalk_content_renderer_client.h',
         'runtime/renderer/xwalk_render_process_observer_generic.cc',
             'runtime/browser/ui/screen_orientation.h',
             'runtime/extension/screen_orientation_extension.cc',
             'runtime/extension/screen_orientation_extension.h',
+            'runtime/browser/tizen/tizen_locale_listener.cc',
+            'runtime/browser/tizen/tizen_locale_listener.h',
           ],
           'sources!':[
             'runtime/browser/runtime_platform_util_linux.cc',
index abfaf67..24136f9 100644 (file)
       'type': 'none',
       'variables': {
         'jni_gen_package': 'xwalk',
-        'jni_generator_ptr_type': 'int',
       },
       'sources': [
         'runtime/android/core/src/org/xwalk/core/AndroidProtocolHandler.java',
         'runtime/android/core/src/org/xwalk/core/XWalkCookieManager.java',
         'runtime/android/core/src/org/xwalk/core/XWalkDevToolsServer.java',
         'runtime/android/core/src/org/xwalk/core/XWalkSettings.java',
+        'runtime/android/core/src/org/xwalk/core/XWalkViewDelegate.java',
         'runtime/android/core/src/org/xwalk/core/XWalkWebContentsDelegate.java',
       ],
       'includes': ['../build/jni_generator.gypi'],
       'type': 'none',
       'variables': {
         'jni_gen_package': 'xwalk',
-        'jni_generator_ptr_type': 'int',
       },
       'sources': [
         'extensions/android/java/src/org/xwalk/core/extensions/XWalkExtensionAndroid.java',
index 3b39d99..aab897a 100644 (file)
@@ -5,6 +5,7 @@
       'type': 'none',
       'dependencies': [
         '../content/content_shell_and_tests.gyp:content_java_test_support',
+        '../net/net.gyp:net_java_test_support',
       ],
       'variables': {
         'java_in_dir': 'test/android/util',
           '<(PRODUCT_DIR)/runtime_client_shell/assets/sampapp-icon-helloworld.png',
           '<(PRODUCT_DIR)/runtime_client_shell/assets/www/manifest_self.json',
           '<(PRODUCT_DIR)/runtime_client_shell/assets/www/manifest_inline_script.json',
+          '<(PRODUCT_DIR)/runtime_client_shell/assets/www/cross_origin.html',
           '<(PRODUCT_DIR)/runtime_client_shell/assets/www/csp.html',
+          '<(PRODUCT_DIR)/runtime_client_shell/assets/www/manifest_without_xwalk_hosts.json',
+          '<(PRODUCT_DIR)/runtime_client_shell/assets/www/manifest_xwalk_hosts.json',
         ],
         'asset_location': '<(PRODUCT_DIR)/runtime_client_shell/assets',
       },
           'files': [
             'test/android/data/www/manifest_self.json',
             'test/android/data/www/manifest_inline_script.json',
+            'test/android/data/www/cross_origin.html',
             'test/android/data/www/csp.html',
+            'test/android/data/www/manifest_without_xwalk_hosts.json',
+            'test/android/data/www/manifest_xwalk_hosts.json',
           ],
         },
       ],
           '<(PRODUCT_DIR)/runtime_client_embedded_shell/assets/xwalk.pak',
           '<(PRODUCT_DIR)/runtime_client_embedded_shell/assets/www/manifest_self.json',
           '<(PRODUCT_DIR)/runtime_client_embedded_shell/assets/www/manifest_inline_script.json',
+          '<(PRODUCT_DIR)/runtime_client_embedded_shell/assets/www/cross_origin.html',
           '<(PRODUCT_DIR)/runtime_client_embedded_shell/assets/www/csp.html',
+          '<(PRODUCT_DIR)/runtime_client_embedded_shell/assets/www/manifest_without_xwalk_hosts.json',
+          '<(PRODUCT_DIR)/runtime_client_embedded_shell/assets/www/manifest_xwalk_hosts.json',
         ],
         'conditions': [
           ['icu_use_data_file_flag==1', {
           'files': [
             'test/android/data/www/manifest_self.json',
             'test/android/data/www/manifest_inline_script.json',
+            'test/android/data/www/cross_origin.html',
             'test/android/data/www/csp.html',
+            'test/android/data/www/manifest_without_xwalk_hosts.json',
+            'test/android/data/www/manifest_xwalk_hosts.json',
           ],
         },
       ],
       ],
       'includes': [ '../build/java_apk.gypi' ],
     },
+    {
+      'target_name': 'xwalk_core_sample_apk',
+      'type': 'none',
+      'dependencies': [
+        'libxwalkcore',
+        'xwalk_core_extensions_java',
+        'xwalk_core_java',
+        'xwalk_core_shell_apk_pak',
+      ],
+      'variables': {
+        'apk_name': 'CrosswalkSample',
+        'java_in_dir': 'runtime/android/sample',
+        'resource_dir': 'runtime/android/sample/res',
+        'native_lib_target': 'libxwalkcore',
+        'additional_input_paths': [
+          '<(PRODUCT_DIR)/sample/assets/index.html',
+          '<(PRODUCT_DIR)/sample/assets/manifest.json',
+          '<(PRODUCT_DIR)/sample/assets/pause_timers.html',
+          '<(PRODUCT_DIR)/sample/assets/xwalk.pak',
+        ],
+        'conditions': [
+          ['icu_use_data_file_flag==1', {
+            'additional_input_paths': [
+              '<(PRODUCT_DIR)/sample/assets/icudtl.dat',
+            ],
+          }],
+        ],
+        'asset_location': '<(PRODUCT_DIR)/sample/assets',
+      },
+      'copies': [
+        {
+          'destination': '<(PRODUCT_DIR)/sample/assets',
+          'files': [
+            'runtime/android/sample/assets/index.html',
+            'runtime/android/sample/assets/manifest.json',
+            'runtime/android/sample/assets/pause_timers.html',
+            '<(PRODUCT_DIR)/xwalk.pak',
+          ],
+          'conditions': [
+            ['icu_use_data_file_flag==1', {
+              'files': [
+                '<(PRODUCT_DIR)/icudtl.dat',
+              ],
+            }],
+          ],
+        },
+      ],
+      'includes': [ '../build/java_apk.gypi' ],
+    },
   ],
 }
index 775d108..f6e9927 100644 (file)
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 {
+  'variables': {
+    'core_library_empty_embedder_apk_name': 'XWalkCoreLibraryEmptyEmbedder',
+  },
   'targets': [
     {
       'target_name': 'pack_xwalk_core_library',
       ],
     },
     {
+      'target_name': 'xwalk_core_library_empty_embedder_apk',
+      'type': 'none',
+      'dependencies': [
+        'libxwalkcore',
+        'xwalk_core_java',
+      ],
+      'variables': {
+        'apk_name': '<(core_library_empty_embedder_apk_name)',
+        'java_in_dir': 'runtime/android/core_library_empty',
+        'native_lib_target': 'libxwalkcore',
+        'is_test_apk': 1,
+        'additional_src_dirs': [
+           '<(DEPTH)/ui/android/java/resource_map',
+           '<(DEPTH)/content/public/android/java/resource_map',
+        ],
+      },
+      'includes': [ '../build/java_apk.gypi' ],
+    },
+    {
+      # pack classes compiled from the java files chromium generated into a
+      # jar file.
+      'target_name': 'chromium_generated_java',
+      'type': 'none',
+      'dependencies': [
+        'xwalk_core_library_empty_embedder_apk',
+      ],
+      'variables': {
+        'jar_name': '<(_target_name).jar',
+        'jar_final_path': '<(PRODUCT_DIR)/lib.java/<(jar_name)',
+        'jar_excluded_classes': [
+          '*org/xwalk/*',
+        ],
+      },
+      'actions': [
+        {
+          'action_name': 'jar_<(_target_name)',
+          'message': 'Creating <(_target_name) jar',
+          'inputs': [
+            '<(DEPTH)/build/android/gyp/util/build_utils.py',
+            '<(DEPTH)/build/android/gyp/util/md5_check.py',
+            '<(DEPTH)/build/android/gyp/jar.py',
+            '<(PRODUCT_DIR)/apks/<(core_library_empty_embedder_apk_name).apk',
+          ],
+          'outputs': [
+            '<(jar_final_path)',
+          ],
+          'action': [
+            'python', '<(DEPTH)/build/android/gyp/jar.py',
+            '--classes-dir=<(PRODUCT_DIR)/xwalk_core_library_empty_embedder_apk/classes',
+            '--jar-path=<(jar_final_path)',
+            '--excluded-classes=<(jar_excluded_classes)',
+          ],
+        },
+      ],
+    },
+    {
+      'target_name': 'xwalk_core_library_java',
+      'type': 'none',
+      'dependencies': [
+        'xwalk_core_java',
+        'chromium_generated_java',
+      ],
+      'variables': {
+        'classes_dir': '<(PRODUCT_DIR)/<(_target_name)/classes',
+        'jar_name': '<(_target_name).jar',
+        'jar_final_path': '<(PRODUCT_DIR)/lib.java/<(jar_name)',
+        #TODO(wang16): figure out why the 'jar_final_path' defined in chromium_generated_java
+        #              not added into following all_dependent_settings setting chain.
+        #              BUG=https://crosswalk-project.org/jira/browse/XWALK-1575
+        'input_jars_paths': ['<(PRODUCT_DIR)/lib.java/chromium_generated_java.jar'],
+      },
+      'all_dependent_settings': {
+        'variables': {
+          'input_jars_paths': ['<(jar_final_path)'],
+        },
+      },
+      'actions': [
+        {
+          'action_name': 'jars_<(_target_name)',
+          'message': 'Creating <(_target_name) jar',
+          'inputs': [
+            'build/android/merge_jars.py',
+          ],
+          'outputs': [
+            '<(PRODUCT_DIR)/pack_xwalk_core_library_java_intermediate/always_run',
+          ],
+          'action': [
+            'python', 'build/android/merge_jars.py',
+            '--classes-dir=<(classes_dir)',
+            '--jars=>(input_jars_paths)',
+            '--jar-path=<(jar_final_path)',
+          ],
+        },
+      ],
+    },
+    {
       'target_name': 'xwalk_core_library',
       'type': 'none',
       'dependencies': [
-        'xwalk_core_shell_apk'
+        'xwalk_core_shell_apk',
+        'xwalk_core_library_java',
       ],
       'actions': [
         {