+++ /dev/null
-Author: Sudarsana Nagineni <sudarsana.nagineni@intel.com>
-
-This patch includes Chromium side changes needed for integrating
-WebMediaPlayer with the Tizen Audio Session Manager.
-
-Also, it has changes that are needed for generating audio-session-manager
-stubs and load the library dynamically in the Browser process.
-
-audio-session-manager is using an _attribute_((constructor)) to initialize
-code and setup signal handlers at startup. So, linking with this library
-is causing a sandbox violation by executing the code in Renderer Process,
-since the Renderer Process and the Browser Process are linked with the
-same libraries.
-
-To prevent the problem, we load the audio-session-manager dynamically in
-the Browser process.
-
-diff --git src/build/linux/system.gyp src/build/linux/system.gyp
-index 4a7e857..f89d256 100644
---- src/build/linux/system.gyp
-+++ src/build/linux/system.gyp
-@@ -874,5 +874,19 @@
- }],
- ],
- },
-+ {
-+ 'target_name': 'audio_session_manager',
-+ 'type': 'none',
-+ 'toolsets': ['host', 'target'],
-+ 'conditions': [
-+ ['tizen_mobile == 1', {
-+ 'direct_dependent_settings': {
-+ 'cflags': [
-+ '<!@(<(pkg-config) --cflags audio-session-mgr)',
-+ ],
-+ },
-+ }],
-+ ],
-+ },
- ],
- }
-diff --git src/content/browser/renderer_host/render_view_host_impl.cc src/content/browser/renderer_host/render_view_host_impl.cc
-index 0912144..adf0a1b 100644
---- src/content/browser/renderer_host/render_view_host_impl.cc
-+++ src/content/browser/renderer_host/render_view_host_impl.cc
-@@ -89,4 +89,6 @@
- #include "content/browser/media/android/browser_media_player_manager.h"
-+#elif defined(OS_TIZEN_MOBILE)
-+#include "xwalk/tizen/browser/browser_mediaplayer_manager.h"
- #elif defined(OS_WIN)
- #include "base/win/win_util.h"
- #endif
-
- using base::TimeDelta;
-@@ -223,6 +225,8 @@ RenderViewHostImpl::RenderViewHostImpl(
-
- #if defined(OS_ANDROID)
- media_player_manager_.reset(BrowserMediaPlayerManager::Create(this));
-+#elif defined(OS_TIZEN_MOBILE)
-+ media_player_manager_.reset(tizen::BrowserMediaPlayerManager::Create(this));
- #endif
- }
-
-diff --git src/content/browser/renderer_host/render_view_host_impl.h src/content/browser/renderer_host/render_view_host_impl.h
-index d63bae3..d0602c7 100644
---- src/content/browser/renderer_host/render_view_host_impl.h
-+++ src/content/browser/renderer_host/render_view_host_impl.h
-@@ -42,6 +42,12 @@ struct ViewHostMsg_ShowPopup_Params;
- struct ViewMsg_Navigate_Params;
- struct ViewMsg_PostMessage_Params;
-
-+#if defined(OS_TIZEN_MOBILE)
-+namespace tizen {
-+class BrowserMediaPlayerManager;
-+}
-+#endif
-+
- namespace base {
- class ListValue;
- }
-@@ -704,6 +710,8 @@ class CONTENT_EXPORT RenderViewHostImpl
- #if defined(OS_ANDROID)
- // Manages all the android mediaplayer objects and handling IPCs for video.
- scoped_ptr<BrowserMediaPlayerManager> media_player_manager_;
-+#elif defined(OS_TIZEN_MOBILE)
-+ scoped_ptr<tizen::BrowserMediaPlayerManager> media_player_manager_;
- #endif
-
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
-diff --git src/content/common/content_message_generator.h src/content/common/content_message_generator.h
-index 78e7c53..a3cda01 100644
---- src/content/common/content_message_generator.h
-+++ src/content/common/content_message_generator.h
-@@ -57,3 +57,6 @@
- #include "content/common/view_messages.h"
- #include "content/common/websocket_messages.h"
- #include "content/common/worker_messages.h"
-+#if defined(OS_TIZEN_MOBILE)
-+#include "xwalk/tizen/common/media_player_messages.h"
-+#endif
-diff --git src/content/content_browser.gypi src/content/content_browser.gypi
-index 6570d15..d47cee2 100644
---- src/content/content_browser.gypi
-+++ src/content/content_browser.gypi
-@@ -1641,5 +1641,69 @@
- 'browser/geolocation/wifi_data_provider_linux.cc',
- ],
- }],
-+ ['tizen_mobile == 1', {
-+ 'sources': [
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager.cc',
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager.h',
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager_init.cc',
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager_init.h',
-+ '<(DEPTH)/xwalk/tizen/browser/browser_mediaplayer_manager.cc',
-+ '<(DEPTH)/xwalk/tizen/browser/browser_mediaplayer_manager.h',
-+ ],
-+ 'variables': {
-+ 'generate_stubs_script': '../tools/generate_stubs/generate_stubs.py',
-+ 'extra_header': '../xwalk/tizen/browser/audio_session_manager_stub_headers.fragment',
-+ 'sig_files': ['../xwalk/tizen/browser/audio_session_manager.sigs'],
-+ 'outfile_type': 'posix_stubs',
-+ 'stubs_filename_root': 'audio_session_manager_stubs',
-+ 'project_path': 'xwalk/tizen/browser',
-+ 'intermediate_dir': '<(INTERMEDIATE_DIR)',
-+ 'output_root': '<(SHARED_INTERMEDIATE_DIR)/audio_session_manager',
-+ },
-+ 'include_dirs': [
-+ '<(output_root)',
-+ ],
-+ 'actions': [
-+ {
-+ 'action_name': 'generate_stubs',
-+ 'inputs': [
-+ '<(generate_stubs_script)',
-+ '<(extra_header)',
-+ '<@(sig_files)',
-+ ],
-+ 'outputs': [
-+ '<(intermediate_dir)/<(stubs_filename_root).cc',
-+ '<(output_root)/<(project_path)/<(stubs_filename_root).h',
-+ ],
-+ 'action': ['python',
-+ '<(generate_stubs_script)',
-+ '-i', '<(intermediate_dir)',
-+ '-o', '<(output_root)/<(project_path)',
-+ '-t', '<(outfile_type)',
-+ '-e', '<(extra_header)',
-+ '-s', '<(stubs_filename_root)',
-+ '-p', '<(project_path)',
-+ '<@(_inputs)',
-+ ],
-+ 'process_outputs_as_sources': 1,
-+ 'message': 'Generating audio session manager stubs for dynamic loading',
-+ },
-+ ],
-+ 'conditions': [
-+ ['OS=="linux" or OS=="solaris"', {
-+ 'link_settings': {
-+ 'libraries': [
-+ '-ldl',
-+ ],
-+ },
-+ }],
-+ ],
-+ 'dependencies': [
-+ '../build/linux/system.gyp:audio_session_manager',
-+ ],
-+ 'export_dependent_settings': [
-+ '../build/linux/system.gyp:audio_session_manager',
-+ ],
-+ }],
- ],
- }
-diff --git src/content/content_common.gypi src/content/content_common.gypi
-index 1bfcccd..46db168 100644
---- src/content/content_common.gypi
-+++ src/content/content_common.gypi
-@@ -656,5 +656,10 @@
- }, {
- 'defines': ['USE_SECCOMP_BPF'],
- }],
-+ ['tizen_mobile == 1', {
-+ 'sources': [
-+ '<(DEPTH)/xwalk/tizen/common/media_player_messages.h',
-+ ],
-+ }],
- ['OS=="win" and directxsdk_exists=="True"', {
- 'actions': [
- {
-diff --git src/content/content_renderer.gypi src/content/content_renderer.gypi
-index 1e72a81..3bceb70 100644
---- src/content/content_renderer.gypi
-+++ src/content/content_renderer.gypi
-@@ -752,6 +752,14 @@
- }],
- ],
- }],
-+ ['tizen_mobile == 1', {
-+ 'sources': [
-+ '<(DEPTH)/xwalk/tizen/renderer/mediaplayer_impl.cc',
-+ '<(DEPTH)/xwalk/tizen/renderer/mediaplayer_impl.h',
-+ '<(DEPTH)/xwalk/tizen/renderer/renderer_mediaplayer_manager.cc',
-+ '<(DEPTH)/xwalk/tizen/renderer/renderer_mediaplayer_manager.h',
-+ ],
-+ }],
- ],
- 'target_conditions': [
- ['OS=="android"', {
-diff --git src/content/renderer/render_view_impl.cc src/content/renderer/render_view_impl.cc
-index c5a7059..cd42b4c 100644
---- src/content/renderer/render_view_impl.cc
-+++ src/content/renderer/render_view_impl.cc
-@@ -245,6 +245,11 @@
- #include "content/renderer/media/rtc_peer_connection_handler.h"
- #endif
-
-+#if defined(OS_TIZEN_MOBILE)
-+#include "xwalk/tizen/renderer/mediaplayer_impl.h"
-+#include "xwalk/tizen/renderer/renderer_mediaplayer_manager.h"
-+#endif
-+
- using blink::WebAXObject;
- using blink::WebApplicationCacheHost;
- using blink::WebApplicationCacheHostClient;
-@@ -844,6 +849,8 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
- body_background_color_(SK_ColorWHITE),
- expected_content_intent_id_(0),
- media_player_manager_(NULL),
-+#elif defined(OS_TIZEN_MOBILE)
-+ media_player_manager_(NULL),
- #endif
- #if defined(OS_WIN)
- focused_plugin_id_(-1),
-@@ -967,6 +974,8 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
- #if defined(OS_ANDROID)
- media_player_manager_ = new RendererMediaPlayerManager(this);
- new JavaBridgeDispatcher(this);
-+#elif defined(OS_TIZEN_MOBILE)
-+ media_player_manager_ = new tizen::RendererMediaPlayerManager(this);
- #endif
-
- // The next group of objects all implement RenderViewObserver, so are deleted
-@@ -3044,6 +3053,13 @@ blink::WebMediaPlayer* RenderViewImpl::CreateMediaPlayer(
- base::Unretained(GetContentClient()->renderer()),
- static_cast<RenderFrame*>(render_frame)),
- sink);
-+
-+#if defined(OS_TIZEN_MOBILE)
-+ tizen::MediaPlayerImpl* media_player = new tizen::MediaPlayerImpl(
-+ frame, client, AsWeakPtr(), media_player_manager_, params);
-+ return media_player;
-+#endif
-+
- return new WebMediaPlayerImpl(frame, client, AsWeakPtr(), params);
- #endif // defined(OS_ANDROID)
- }
-diff --git src/content/renderer/render_view_impl.h src/content/renderer/render_view_impl.h
-index ccfd1b5..8949cd0 100644
---- src/content/renderer/render_view_impl.h
-+++ src/content/renderer/render_view_impl.h
-@@ -128,6 +128,12 @@ namespace webkit_glue {
- class WebURLResponseExtraDataImpl;
- }
-
-+#if defined(OS_TIZEN_MOBILE)
-+namespace tizen {
-+class RendererMediaPlayerManager;
-+}
-+#endif
-+
- namespace content {
- class BrowserPluginManager;
- class DeviceOrientationDispatcher;
-@@ -1403,6 +1409,10 @@ class CONTENT_EXPORT RenderViewImpl
-
- // A date/time picker object for date and time related input elements.
- scoped_ptr<RendererDateTimePicker> date_time_picker_client_;
-+#elif defined(OS_TIZEN_MOBILE)
-+ // The media player manager for managing all the media players on this view
-+ // and for communicating with the audio session manager in browser process.
-+ tizen::RendererMediaPlayerManager* media_player_manager_;
- #endif
-
- // Plugins -------------------------------------------------------------------
%endif
Name: crosswalk
-Version: 9.38.198.0
+Version: 9.38.204.0
Release: 0
-Summary: Crosswalk is an app runtime based on Chromium
+Summary: Chromium-based app runtime
License: (BSD-3-Clause and LGPL-2.1+)
Group: Web Framework/Web Run Time
Url: https://github.com/otcshare/crosswalk
BuildRequires: pkgconfig(xtst)
%endif
+%if "%{profile}" == "ivi"
+BuildRequires: pkgconfig(murphy-common)
+BuildRequires: pkgconfig(murphy-resource)
+%endif
+
%if %{with wayland}
BuildRequires: pkgconfig(wayland-client)
BuildRequires: pkgconfig(wayland-cursor)
fi
%if %{with wayland}
-GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1 -Denable_xdg_shell=0"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1 -Denable_xdg_shell=1"
%endif
GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Ddisable_nacl=%{_disable_nacl}"
export FFLAGS=`echo $FFLAGS | sed s,-mfpu=vfpv3,-mfpu=neon,g`
%endif
+%if "%{profile}" == "ivi"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Denable_murphy=1"
+%endif
+
# --no-parallel is added because chroot does not mount a /dev/shm, this will
# cause python multiprocessing.SemLock error.
export GYP_GENERATORS='ninja'
install -p -D src/out/Release/libffmpegsumo.so %{buildroot}%{_libdir}/xwalk/libffmpegsumo.so
install -p -D src/out/Release/xwalk.pak %{buildroot}%{_libdir}/xwalk/xwalk.pak
mkdir -p %{buildroot}%{_datadir}/xwalk
-install -p -D src/xwalk/application/common/installer/tizen/configuration/*.xsd %{buildroot}%{_datadir}/xwalk/
+install -p -D src/xwalk/application/common/tizen/configuration/*.xsd %{buildroot}%{_datadir}/xwalk/
# PNaCl
%if ! %{_disable_nacl}
[Service]
Type=dbus
BusName=org.crosswalkproject.Runtime1
+Environment=OZONE_WAYLAND_USE_XDG_SHELL='defined'
ExecStart=@LIB_INSTALL_DIR@/xwalk/xwalk --external-extensions-path=@LIB_INSTALL_DIR@/tizen-extensions-crosswalk
# Whether to allow building of the GPU-related isolates.
'archive_gpu_tests%': 0,
+
+ # Flags to enable Murphy resource policy daemon integration on Tizen.
+ 'tizen%': 0,
+ 'enable_murphy%': 0,
},
'target_defaults': {
'variables': {
}],
],
},
+ {
+ 'target_name': 'resource_manager',
+ 'type': 'none',
+ 'toolsets': ['host', 'target'],
+ 'conditions': [
+ ['tizen==1 and enable_murphy==1', {
+ 'direct_dependent_settings': {
+ 'cflags': [
+ '<!@(<(pkg-config) --cflags murphy-common murphy-resource)',
+ ],
+ },
+ 'link_settings': {
+ 'ldflags': [
+ '<!@(<(pkg-config) --libs-only-L --libs-only-other murphy-common murphy-resource)',
+ ],
+ 'libraries': [
+ '<!@(<(pkg-config) --libs-only-l murphy-common murphy-resource)',
+ ],
+ },
+ }],
+ ],
+ },
],
}
#include "content/browser/media/media_web_contents_observer.h"
#endif
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+#include "xwalk/tizen/browser/media/media_webcontents_observer.h"
+#endif
+
using base::TimeDelta;
using blink::WebConsoleMessage;
using blink::WebDragOperation;
media_web_contents_observer_.reset(new MediaWebContentsObserver(this));
#endif
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+ media_webcontents_observer_.reset(new tizen::MediaWebContentsObserver(this));
+#endif
+
unload_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
&RenderViewHostImpl::OnSwappedOut, weak_factory_.GetWeakPtr(), true)));
}
struct FrameMsg_Navigate_Params;
struct ViewMsg_PostMessage_Params;
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+namespace tizen {
+class MediaWebContentsObserver;
+}
+#endif
+
namespace base {
class ListValue;
}
scoped_ptr<MediaWebContentsObserver> media_web_contents_observer_;
#endif
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+ // Manages all the media player managers and forwards IPCs to them.
+ scoped_ptr<tizen::MediaWebContentsObserver> media_webcontents_observer_;
+#endif
+
// Used to swap out or shutdown this RVH when the unload event is taking too
// long to execute, depending on the number of active views in the
// SiteInstance.
#include "content/common/gin_java_bridge_messages.h"
#include "content/common/media/media_player_messages_android.h"
#endif // defined(OS_ANDROID)
+
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+#include "xwalk/tizen/common/media/media_player_messages.h"
+#endif
'browser/power_save_blocker_x11.cc',
],
}],
+ ['tizen==1 and enable_murphy==1', {
+ 'sources': [
+ '<(DEPTH)/xwalk/tizen/browser/media/browser_mediaplayer_manager.cc',
+ '<(DEPTH)/xwalk/tizen/browser/media/browser_mediaplayer_manager.h',
+ '<(DEPTH)/xwalk/tizen/browser/media/media_webcontents_observer.cc',
+ '<(DEPTH)/xwalk/tizen/browser/media/media_webcontents_observer.h',
+ '<(DEPTH)/xwalk/tizen/browser/media/murphy_mainloop.cc',
+ '<(DEPTH)/xwalk/tizen/browser/media/murphy_mainloop.h',
+ '<(DEPTH)/xwalk/tizen/browser/media/murphy_resource.cc',
+ '<(DEPTH)/xwalk/tizen/browser/media/murphy_resource.h',
+ '<(DEPTH)/xwalk/tizen/browser/media/murphy_resource_manager.cc',
+ '<(DEPTH)/xwalk/tizen/browser/media/murphy_resource_manager.h',
+ ],
+ 'dependencies': [
+ '../build/linux/system.gyp:resource_manager',
+ ],
+ 'export_dependent_settings': [
+ '../build/linux/system.gyp:resource_manager',
+ ],
+ }],
['os_bsd==1', {
'sources/': [
['exclude', '^browser/gamepad/gamepad_platform_data_fetcher_linux\\.cc$'],
'<(DEPTH)/third_party/khronos',
],
}],
+ ['tizen==1 and enable_murphy==1', {
+ 'sources': [
+ '<(DEPTH)/xwalk/tizen/common/media/media_player_messages.h',
+ ],
+ }],
['OS=="win" and directxsdk_exists=="True"', {
'actions': [
{
'renderer/media/crypto/renderer_cdm_manager.h',
],
}],
+ ['tizen==1 and enable_murphy==1', {
+ 'sources': [
+ '<(DEPTH)/xwalk/tizen/renderer/media/mediaplayer_impl.cc',
+ '<(DEPTH)/xwalk/tizen/renderer/media/mediaplayer_impl.h',
+ '<(DEPTH)/xwalk/tizen/renderer/media/renderer_mediaplayer_manager.cc',
+ '<(DEPTH)/xwalk/tizen/renderer/media/renderer_mediaplayer_manager.h',
+ ],
+ }],
],
'target_conditions': [
['OS=="android"', {
#include "content/renderer/media/crypto/renderer_cdm_manager.h"
#endif
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+#include "xwalk/tizen/renderer/media/renderer_mediaplayer_manager.h"
+#include "xwalk/tizen/renderer/media/mediaplayer_impl.h"
+#endif
+
using blink::WebContextMenuData;
using blink::WebData;
using blink::WebDataSource;
#if defined(VIDEO_HOLE)
contains_media_player_(false),
#endif
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+ media_player_manager_(NULL),
+#endif
geolocation_dispatcher_(NULL),
push_messaging_dispatcher_(NULL),
screen_orientation_dispatcher_(NULL),
static_cast<RenderFrame*>(this)),
RenderThreadImpl::current()->GetAudioRendererMixerManager()->CreateInput(
render_view_->routing_id_, routing_id_));
+
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+ tizen::MediaPlayerImpl* media_player = new tizen::MediaPlayerImpl(
+ frame, client, weak_factory_.GetWeakPtr(),
+ GetTizenMediaPlayerManager(), params);
+ return media_player;
+#endif
+
return new WebMediaPlayerImpl(frame, client, weak_factory_.GetWeakPtr(),
params);
#endif // defined(OS_ANDROID)
}
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+tizen::RendererMediaPlayerManager*
+RenderFrameImpl::GetTizenMediaPlayerManager() {
+ if (!media_player_manager_)
+ media_player_manager_ = new tizen::RendererMediaPlayerManager(this);
+
+ return media_player_manager_;
+}
+#endif
+
blink::WebContentDecryptionModule*
RenderFrameImpl::createContentDecryptionModule(
blink::WebLocalFrame* frame,
class Rect;
}
+#if defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+namespace tizen {
+class RendererMediaPlayerManager;
+}
+#endif
+
namespace content {
class ChildFrameCompositingHelper;
blink::WebMediaPlayerClient* client);
RendererMediaPlayerManager* GetMediaPlayerManager();
+#elif defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+ tizen::RendererMediaPlayerManager* GetTizenMediaPlayerManager();
#endif
#if defined(ENABLE_BROWSER_CDMS)
// real media player in the browser process. It's okay to use a raw pointer
// since it's a RenderFrameObserver.
RendererMediaPlayerManager* media_player_manager_;
+#elif defined(OS_TIZEN) && defined(ENABLE_MURPHY)
+ tizen::RendererMediaPlayerManager* media_player_manager_;
#endif
#if defined(ENABLE_BROWSER_CDMS)
+Changbin Shao <changbin.shao@intel.com>
Daniel Narvaez <dwnarvaez@gmail.com>
Dongseong Hwang <dongseong.hwang@intel.com>
Eduardo Lima (Etrunko) <eduardo.lima@intel.com>
VAStatus vaSyncSurface(VADisplay dpy, VASurfaceID render_target);
VAStatus vaTerminate(VADisplay dpy);
VAStatus vaUnmapBuffer(VADisplay dpy, VABufferID buf_id);
-
+VAStatus vaLockBuffer(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info_ptr);
+VAStatus vaUnlockBuffer(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info_ptr);
#------------------------------------------------
# Functions from libva-wayland used in chromium code.
#include "ozone/media/vaapi_video_decode_accelerator.h"
+#include <string>
+
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "content/common/gpu/gpu_channel.h"
#include "media/base/bind_to_current_loop.h"
#include "media/video/picture.h"
-#include "ui/gl/scoped_binders.h"
+#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/scoped_binders.h"
static void ReportToUMA(
media::VaapiH264Decoder::VAVDAH264DecoderFailure failure) {
return size_;
}
+ VAImage* va_image() {
+ return va_image_.get();
+ }
+
// Upload vaimage data to texture. Needs to be called every frame.
bool Upload(VASurfaceID id);
+ // Bind EGL image to texture. Needs to be called every frame.
+ bool Bind();
+ bool UpdateEGLImage(VASurfaceID id);
+
private:
TFPPicture(const base::Callback<bool(void)>& make_context_current, //NOLINT
VaapiWrapper* va_wrapper,
bool Initialize();
+ EGLImageKHR CreateEGLImage(
+ EGLDisplay egl_display, VASurfaceID surface, VAImage* va_image);
+ bool DestroyEGLImage(EGLDisplay egl_display, EGLImageKHR egl_image);
+
base::Callback<bool(void)> make_context_current_; //NOLINT
VaapiWrapper* va_wrapper_;
uint32 texture_id_;
gfx::Size size_;
- VAImage va_image_;
+ scoped_ptr<VAImage> va_image_;
+ EGLImageKHR egl_image_;
+ EGLDisplay egl_display_;
DISALLOW_COPY_AND_ASSIGN(TFPPicture);
};
va_wrapper_(va_wrapper),
picture_buffer_id_(picture_buffer_id),
texture_id_(texture_id),
- size_(size) {
+ size_(size),
+ va_image_(new VAImage()),
+ egl_display_(gfx::GLSurfaceEGL::GetHardwareDisplay()) {
DCHECK(!make_context_current_.is_null());
-};
+ DCHECK(va_image_);
+}
linked_ptr<VaapiVideoDecodeAccelerator::TFPPicture>
VaapiVideoDecodeAccelerator::TFPPicture::Create(
if (!make_context_current_.Run())
return false;
- if (!va_wrapper_->CreateRGBImage(size_, &va_image_)) {
+ if (!va_wrapper_->CreateRGBImage(size_, va_image_.get())) {
DVLOG(1) << "Failed to create VAImage";
return false;
}
VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
DCHECK(CalledOnValidThread());
+ if (egl_image_ != EGL_NO_IMAGE_KHR)
+ DestroyEGLImage(egl_display_, egl_image_);
+
if (va_wrapper_) {
- va_wrapper_->DestroyImage(&va_image_);
+ va_wrapper_->DestroyImage(va_image_.get());
+ }
+}
+
+bool VaapiVideoDecodeAccelerator::TFPPicture::UpdateEGLImage(
+ VASurfaceID surface) {
+ DCHECK(CalledOnValidThread());
+
+ if (!make_context_current_.Run())
+ return false;
+
+ if (egl_image_ != EGL_NO_IMAGE_KHR)
+ DestroyEGLImage(egl_display_, egl_image_);
+
+ egl_image_ = CreateEGLImage(egl_display_, surface, va_image_.get());
+ if (egl_image_ == EGL_NO_IMAGE_KHR) {
+ DVLOG(1) << "Failed to create EGL image";
+ return false;
}
+
+ return true;
}
bool VaapiVideoDecodeAccelerator::TFPPicture::Upload(VASurfaceID surface) {
if (!make_context_current_.Run())
return false;
- if (!va_wrapper_->PutSurfaceIntoImage(surface, &va_image_)) {
+ if (!va_wrapper_->PutSurfaceIntoImage(surface, va_image_.get())) {
DVLOG(1) << "Failed to put va surface to image";
return false;
}
void* buffer = NULL;
- if (!va_wrapper_->MapImage(&va_image_, &buffer)) {
+ if (!va_wrapper_->MapImage(va_image_.get(), &buffer)) {
DVLOG(1) << "Failed to map VAImage";
return false;
}
// texture output implementation. It can be removed when zero buffer copy
// is implemented.
unsigned int al = 4 * size_.width();
- if (al != va_image_.pitches[0]) {
+ if (al != va_image_->pitches[0]) {
// Not aligned phenomenon occurs only in special size video in None-X11.
// So re-check RGBA data alignment and realign filled video frame in need.
unsigned char* bhandle = static_cast<unsigned char*>(buffer);
for (int i = 0; i < size_.height(); i++) {
- memcpy(bhandle + (i * al), bhandle + (i * (va_image_.pitches[0])), al);
+ memcpy(bhandle + (i * al), bhandle + (i * (va_image_->pitches[0])), al);
}
}
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.width(), size_.height(),
- 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_BGRA,
+ size_.width(),
+ size_.height(),
+ 0,
+ GL_BGRA,
+ GL_UNSIGNED_BYTE,
+ buffer);
+
+ va_wrapper_->UnmapImage(va_image_.get());
+
+ return true;
+}
- va_wrapper_->UnmapImage(&va_image_);
+bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
+ DCHECK(CalledOnValidThread());
+ if (!make_context_current_.Run())
+ return false;
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
return true;
}
+EGLImageKHR VaapiVideoDecodeAccelerator::TFPPicture::CreateEGLImage(
+ EGLDisplay egl_display, VASurfaceID va_surface, VAImage* va_image) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(va_image);
+
+ VABufferInfo buffer_info;
+ if (!va_wrapper_->LockBuffer(va_surface, va_image->buf, &buffer_info)) {
+ DVLOG(1) << "Failed to lock Buffer";
+ return EGL_NO_IMAGE_KHR;
+ }
+
+ EGLint attribs[] = {
+ EGL_WIDTH, 0,
+ EGL_HEIGHT, 0,
+ EGL_DRM_BUFFER_STRIDE_MESA, 0,
+ EGL_DRM_BUFFER_FORMAT_MESA,
+ EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
+ EGL_DRM_BUFFER_USE_MESA,
+ EGL_DRM_BUFFER_USE_SHARE_MESA,
+ EGL_NONE };
+ attribs[1] = va_image->width;
+ attribs[3] = va_image->height;
+ attribs[5] = va_image->pitches[0] / 4;
+
+ EGLImageKHR egl_image = eglCreateImageKHR(
+ egl_display,
+ EGL_NO_CONTEXT,
+ EGL_DRM_BUFFER_MESA,
+ (EGLClientBuffer) buffer_info.handle,
+ attribs);
+
+ if (va_wrapper_) {
+ va_wrapper_->UnlockBuffer(va_surface, va_image->buf, &buffer_info);
+ }
+
+ return egl_image;
+}
+
+bool VaapiVideoDecodeAccelerator::TFPPicture::DestroyEGLImage(
+ EGLDisplay egl_display, EGLImageKHR egl_image) {
+ return eglDestroyImageKHR(egl_display, egl_image);
+}
+
VaapiVideoDecodeAccelerator::TFPPicture*
VaapiVideoDecodeAccelerator::TFPPictureById(int32 picture_buffer_id) {
TFPPictures::iterator it = tfp_pictures_.find(picture_buffer_id);
return false;
}
+ supports_valockBuffer_apis_ = vaapi_wrapper_->SupportsVaLockBufferApis();
+ std::string query =
+ supports_valockBuffer_apis_ ? "supports" : "doesn't support";
+ LOG(INFO) << "VAAPI " << query << " vaLockBuffer apis";
+
decoder_.reset(
new VaapiH264Decoder(
vaapi_wrapper_.get(),
"output_id", output_id);
DVLOG(3) << "Outputting VASurface " << va_surface->id()
- << " into pixmap bound to picture buffer id " << output_id;
+ << " into texture bound to picture buffer id " << output_id;
- RETURN_AND_NOTIFY_ON_FAILURE(tfp_picture->Upload(va_surface->id()),
- "Failed to upload VASurface to texture",
- PLATFORM_FAILURE, ); //NOLINT
+ if (supports_valockBuffer_apis_) {
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ vaapi_wrapper_->PutSurfaceIntoImage(
+ va_surface->id(),
+ tfp_picture->va_image()),
+ "Failed putting surface into vaimage",
+ PLATFORM_FAILURE, ); //NOLINT
+
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ tfp_picture->UpdateEGLImage(va_surface->id()),
+ "Failed to update egl image per vaimage info",
+ PLATFORM_FAILURE, ); //NOLINT
+
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ tfp_picture->Bind(),
+ "Failed to bind egl image to texture",
+ PLATFORM_FAILURE, ); //NOLINT
+ } else {
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ tfp_picture->Upload(va_surface->id()),
+ "Failed to upload VASurface to texture",
+ PLATFORM_FAILURE, ); //NOLINT
+ }
// Notify the client a picture is ready to be displayed.
++num_frames_at_client_;
// The WeakPtrFactory for |weak_this_|.
base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_;
+ // Whether VaapiWrapper supports vaLockBuffer apis.
+ bool supports_valockBuffer_apis_;
+
DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator);
};
#include "media/media/va_stubs.h"
#include "third_party/libva/va/wayland/va_wayland.h"
+#include "third_party/libva/va/va_drmcommon.h"
using media_media::kModuleVa_wayland;
using media_media::InitializeStubs;
static const base::FilePath::CharType kVaLib[] =
FILE_PATH_LITERAL("libva-wayland.so.1");
+static const char kVaLockBufferSymbol[] = "vaLockBuffer";
+static const char kVaUnlockBufferSymbol[] = "vaUnlockBuffer";
+
#define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \
do { \
DVLOG(1) << err_msg \
base::AutoLock auto_lock(va_lock_);
VAStatus va_res;
VAImageFormat format;
- format.fourcc = VA_FOURCC_RGBX;
+ format.fourcc = VA_FOURCC_BGRX;
format.byte_order = VA_LSB_FIRST;
format.bits_per_pixel = 32;
format.depth = 24;
- format.red_mask = 0xff;
- format.green_mask = 0xff00;
+ format.red_mask = 0x0000ff;
+ format.green_mask = 0x00ff00;
format.blue_mask = 0xff0000;
format.alpha_mask = 0;
+
va_res = vaCreateImage(va_display_,
&format,
size.width(),
VA_SUCCESS_OR_RETURN(va_res, "Failed to put surface into image", false);
return true;
}
+
+bool VaapiWrapper::LockBuffer(VASurfaceID va_surface_id,
+ VABufferID buf_id,
+ VABufferInfo* buf_info) {
+ DCHECK(buf_info);
+ base::AutoLock auto_lock(va_lock_);
+
+ buf_info->mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
+ VAStatus va_res = vaLockBuffer(va_display_, buf_id, buf_info);
+ VA_SUCCESS_OR_RETURN(va_res, "Failed to lock vabuffer", false);
+
+ return true;
+}
+
+bool VaapiWrapper::UnlockBuffer(VASurfaceID va_surface_id,
+ VABufferID buf_id,
+ VABufferInfo* buf_info) {
+ DCHECK(buf_info);
+ base::AutoLock auto_lock(va_lock_);
+ VAStatus va_res = vaUnlockBuffer(va_display_, buf_id, buf_info);
+ VA_SUCCESS_OR_RETURN(va_res, "Failed to unlock vabuffer", false);
+
+ return true;
+}
+
+
bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
VAImage* image,
void** mem) {
return ret;
}
+bool VaapiWrapper::SupportsVaLockBufferApis() {
+ void* handle = dlopen(kVaLib, RTLD_LAZY);
+ if (!handle) {
+ LOG(ERROR) << "Could not open " << kVaLib;
+ return false;
+ }
+ return dlsym(handle, kVaLockBufferSymbol) &&
+ dlsym(handle, kVaUnlockBufferSymbol);
+}
+
} // namespace media
// Put data from |va_surface_id| into |va_image|, converting/scaling it.
bool PutSurfaceIntoImage(VASurfaceID va_surface_id,
VAImage* va_image);
+
+ bool LockBuffer(VASurfaceID va_surface_id,
+ VABufferID buf_id,
+ VABufferInfo* buf_info);
+ bool UnlockBuffer(VASurfaceID va_surface_id,
+ VABufferID buf_id,
+ VABufferInfo* buf_info);
+
// Returns true if the VAAPI version is less than the specified version.
bool VAAPIVersionLessThan(int major, int minor);
// GetVaImage(). This is intended for testing only.
void ReturnVaImageForTesting(VAImage* image);
+ // Return true if libva supports vaLockBuffer & vaUnlockBuffer apis.
+ bool SupportsVaLockBufferApis();
+
private:
VaapiWrapper();
--- /dev/null
+From e06df3445ac9a82446ddba30e2978cc693d39574 Mon Sep 17 00:00:00 2001
+From: Shao Changbin <changbin.shao@intel.com>
+Date: Thu, 4 Sep 2014 12:44:01 +0800
+Subject: [PATCH] Introduce vaLockBuffer APIs in libva.
+
+---
+ third_party/libva/va/va.h | 111 ++++++++++++++++++++++++++++++++++++++
+ third_party/libva/va/va_backend.h | 14 +++++
+ 2 files changed, 125 insertions(+)
+
+diff --git a/third_party/libva/va/va.h b/third_party/libva/va/va.h
+index 845760c..9455023 100644
+--- a/third_party/libva/va/va.h
++++ b/third_party/libva/va/va.h
+@@ -78,6 +78,7 @@
+ #ifndef _VA_H_
+ #define _VA_H_
+
++#include <stddef.h>
+ #include <stdint.h>
+ #include <va/va_version.h>
+
+@@ -1851,6 +1852,116 @@ VAStatus vaDestroyBuffer (
+ VABufferID buffer_id
+ );
+
++/** VA buffer information */
++typedef struct {
++ /** Buffer handle */
++ uintptr_t handle;
++ /** Buffer type (See VABufferType). */
++ uint32_t type;
++ /**
++ * Buffer memory type (See VASurfaceAttribMemoryType).
++ *
++ * On input to vaLockBuffer(), this field can serve as a hint to
++ * specify the set of memory types the caller is interested in. On
++ * successful return from vaLockBuffer(), the field is updated
++ * with the best matching memory type.
++ */
++ uint32_t mem_type;
++ /** Size of the underlying buffer. */
++ size_t mem_size;
++} VABufferInfo;
++
++/**
++ * Locks buffer for external API usage.
++ *
++ * Locks the VA buffer object buf_id for external API usage like
++ * EGL or OpenCL (OCL). This function is a synchronization point. This
++ * means that any pending operation is guaranteed to be completed
++ * prior to returning from the function.
++ *
++ * If the referenced VA buffer object is the backing store of a VA
++ * surface, then this function acts as if vaSyncSurface() on the
++ * parent surface was called first.
++ *
++ * The VABufferInfo argument shall be zero'ed on input. On
++ * successful output, the data structure is filled in with all the
++ * necessary buffer level implementation details like handle, type,
++ * memory type and memory size.
++ *
++ * Note: the external API implementation, or the application, can
++ * express the memory types it is interested in by filling in the
++ * mem_type field accordingly. On successful output, the memory type
++ * that fits best the request and that was used is updated in the
++ * VABufferInfo data structure. If none of the supplied memory types
++ * is supported, then a VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
++ * error is returned.
++ *
++ * The VABufferInfo data is valid until vaUnlockBuffer() is
++ * called. Besides, no additional operation is allowed on any of the
++ * buffer parent object until vaUnlockBuffer() is called. e.g. decoding
++ * into a VA surface backed with the supplied VA buffer object
++ * buf_id would fail with a VA_STATUS_ERROR_SURFACE_BUSY error.
++ *
++ * Possible errors:
++ * - VA_STATUS_ERROR_UNIMPLEMENTED: the VA driver implementation
++ * does not support this interface
++ * - VA_STATUS_ERROR_INVALID_DISPLAY: an invalid display was supplied
++ * - VA_STATUS_ERROR_INVALID_BUFFER: an invalid buffer was supplied
++ * - VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE: the implementation
++ * does not support exporting buffers of the specified type
++ * - VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE: none of the requested
++ * memory types in \ref VABufferInfo.mem_type was supported
++ *
++ * @param[in] dpy the VA display
++ * @param[in] buf_id the VA buffer
++ * @param[in,out] buf_info_ptr the VA buffer information
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus
++vaLockBuffer(
++ VADisplay dpy,
++ VABufferID buf_id,
++ VABufferInfo * buf_info_ptr
++);
++
++/**
++ * Unlocks buffer after usage from external API.
++ *
++ * Unlocks the VA buffer object buf_id from external API usage like
++ * EGL or OpenCL (OCL). This function is a synchronization point. This
++ * means that any pending operation is guaranteed to be completed
++ * prior to returning from the function.
++ *
++ * The VABufferInfo argument shall point to the original data
++ * structure that was obtained from vaLockBuffer(), unaltered. This is
++ * necessary so that the VA driver implementation could deallocate any
++ * resources that were needed.
++ *
++ * In any case, returning from this function invalidates any contents
++ * in VABufferInfo. i.e. the underlyng buffer handle is no longer
++ * valid. Therefore, VA driver implementations are free to reset this
++ * data structure to safe defaults.
++ *
++ * Possible errors:
++ * - VA_STATUS_ERROR_UNIMPLEMENTED: the VA driver implementation
++ * does not support this interface
++ * - VA_STATUS_ERROR_INVALID_DISPLAY: an invalid display was supplied
++ * - VA_STATUS_ERROR_INVALID_BUFFER: an invalid buffer was supplied
++ * - VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE: the implementation
++ * does not support exporting buffers of the specified type
++ *
++ * @param[in] dpy the VA display
++ * @param[in] buf_id the VA buffer
++ * @param[in,out] buf_info_ptr the VA buffer information
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus
++vaUnlockBuffer(
++ VADisplay dpy,
++ VABufferID buf_id,
++ VABufferInfo * buf_info_ptr
++);
++
+ /*
+ Render (Decode) Pictures
+
+diff --git a/third_party/libva/va/va_backend.h b/third_party/libva/va/va_backend.h
+index bd82849..150f8ef 100644
+--- a/third_party/libva/va/va_backend.h
++++ b/third_party/libva/va/va_backend.h
+@@ -420,6 +420,20 @@ struct VADriverVTable
+ VASurfaceAttrib *attrib_list,
+ unsigned int *num_attribs
+ );
++
++ VAStatus
++ (*vaLockBuffer)(
++ VADriverContextP ctx,
++ VABufferID buf_id,
++ VABufferInfo * buf_info_ptr
++ );
++
++ VAStatus
++ (*vaUnlockBuffer)(
++ VADriverContextP ctx,
++ VABufferID buf_id,
++ VABufferInfo * buf_info_ptr
++ );
+ };
+
+ struct VADriverContext
+--
+1.9.1
+
ui::WindowShowState* show_state) const {
*bounds = GetRestoredBounds();
- if (IsFullscreen()) {
- *show_state = ui::SHOW_STATE_FULLSCREEN;
- } else if (IsMinimized()) {
+ if (IsMinimized()) {
*show_state = ui::SHOW_STATE_MINIMIZED;
+ } else if (IsFullscreen()) {
+ *show_state = ui::SHOW_STATE_FULLSCREEN;
} else if (IsMaximized()) {
*show_state = ui::SHOW_STATE_MAXIMIZED;
} else if (!IsActive()) {
if (state_ & Minimized)
return;
- state_ &= ~Maximized;
state_ |= Minimized;
- state_ &= ~Normal;
previous_bounds_ = bounds_;
ui::WindowStateChangeHandler::GetInstance()->SetWidgetState(window_,
ui::MINIMIZED);
}
}
+void DesktopWindowTreeHostWayland::HandleWindowUnminimized() {
+ state_ &= ~Minimized;
+}
+
void DesktopWindowTreeHostWayland::HandleCommit(const std::string& text) {
ui::InputMethodAuraLinux* inputMethod =
static_cast<ui::InputMethodAuraLinux*>(desktop_native_widget_aura_->
void HandleNativeWidgetActivationChanged(bool active);
void HandleWindowResize(unsigned width, unsigned height);
+ void HandleWindowUnminimized();
void HandlePreeditChanged(const std::string& text, const std::string& commit);
void HandleCommit(const std::string& text);
window->HandleWindowResize(width, height);
}
+void WindowTreeHostDelegateWayland::OnWindowUnminimized(unsigned handle) {
+ DesktopWindowTreeHostWayland* window =
+ DesktopWindowTreeHostWayland::GetHostForAcceleratedWidget(handle);
+ DCHECK(window);
+ window->HandleWindowUnminimized();
+}
+
void WindowTreeHostDelegateWayland::OnCommit(unsigned handle,
const std::string& text) {
DesktopWindowTreeHostWayland* window =
virtual void OnWindowResized(unsigned windowhandle,
unsigned width,
unsigned height) OVERRIDE;
+ virtual void OnWindowUnminimized(unsigned windowhandle) OVERRIDE;
virtual void OnPreeditChanged(unsigned handle,
const std::string& text,
const std::string& commit) OVERRIDE;
height));
}
+void EventConverterInProcess::WindowUnminimized(unsigned handle) {
+ ui::EventConverterOzoneWayland::PostTaskOnMainLoop(base::Bind(
+ &EventConverterInProcess::NotifyWindowUnminimized, this, handle));
+}
+
void EventConverterInProcess::Commit(unsigned handle, const std::string& text) {
ui::EventConverterOzoneWayland::PostTaskOnMainLoop(base::Bind(
&EventConverterInProcess::NotifyCommit, this, handle, text));
}
void
+EventConverterInProcess::NotifyWindowUnminimized(EventConverterInProcess* data,
+ unsigned handle) {
+ if (data->observer_)
+ data->observer_->OnWindowUnminimized(handle);
+}
+
+void
EventConverterInProcess::NotifyCommit(EventConverterInProcess* data,
unsigned handle,
const std::string& text) {
virtual void WindowResized(unsigned windowhandle,
unsigned width,
unsigned height) OVERRIDE;
+ virtual void WindowUnminimized(unsigned windowhandle) OVERRIDE;
virtual void Commit(unsigned handle, const std::string& text) OVERRIDE;
virtual void PreeditChanged(unsigned handle, const std::string& text,
unsigned handle,
unsigned width,
unsigned height);
+ static void NotifyWindowUnminimized(EventConverterInProcess* data,
+ unsigned handle);
static void NotifyCommit(EventConverterInProcess* data, unsigned handle,
const std::string& text);
static void NotifyPreeditChanged(EventConverterInProcess* data,
virtual void WindowResized(unsigned windowhandle,
unsigned width,
unsigned height) = 0;
+ virtual void WindowUnminimized(unsigned windowhandle) = 0;
virtual void CloseWidget(unsigned handle) = 0;
virtual void Commit(unsigned handle, const std::string& text) = 0;
virtual void PreeditChanged(unsigned handle, const std::string& text,
Dispatch(new WaylandWindow_Resized(handle, width, height));
}
+void RemoteEventDispatcher::WindowUnminimized(unsigned handle) {
+ Dispatch(new WaylandWindow_Unminimized(handle));
+}
+
void RemoteEventDispatcher::CloseWidget(unsigned handle) {
Dispatch(new WaylandInput_CloseWidget(handle));
}
virtual void WindowResized(unsigned handle,
unsigned width,
unsigned height) OVERRIDE;
+ virtual void WindowUnminimized(unsigned windowhandle) OVERRIDE;
virtual void CloseWidget(unsigned handle) OVERRIDE;
virtual void Commit(unsigned handle, const std::string& text) OVERRIDE;
virtual void OnWindowResized(unsigned windowhandle,
unsigned width,
unsigned height) = 0;
+ virtual void OnWindowUnminimized(unsigned windowhandle) = 0;
// FIXME(joone): Move to IMEChangeObserver?
virtual void OnPreeditChanged(unsigned handle,
const std::string& text,
unsigned /* width */,
unsigned /* height */)
+IPC_MESSAGE_CONTROL1(WaylandWindow_Unminimized, // NOLINT(readability/fn_size)
+ unsigned /*handle*/)
+
IPC_MESSAGE_CONTROL4(WaylandWindow_State, // NOLINT(readability/fn_size)
unsigned /* window handle */,
ui::WidgetState /*state*/,
IPC_MESSAGE_HANDLER(WaylandInput_OutputSize, OnOutputSizeChanged)
IPC_MESSAGE_HANDLER(WaylandInput_CloseWidget, OnCloseWidget)
IPC_MESSAGE_HANDLER(WaylandWindow_Resized, OnWindowResized)
+ IPC_MESSAGE_HANDLER(WaylandWindow_Unminimized, OnWindowUnminimized)
IPC_MESSAGE_HANDLER(WaylandInput_Commit, OnCommit)
IPC_MESSAGE_HANDLER(WaylandInput_PreeditChanged, OnPreeditChanged)
IPC_MESSAGE_HANDLER(WaylandInput_PreeditEnd, OnPreeditEnd)
event_converter_->WindowResized(handle, width, height);
}
+void OzoneChannelHost::OnWindowUnminimized(unsigned handle) {
+ event_converter_->WindowUnminimized(handle);
+}
+
void OzoneChannelHost::OnCommit(unsigned handle, std::string text) {
event_converter_->Commit(handle, text);
}
void OnWindowResized(unsigned handle,
unsigned width,
unsigned height);
+ void OnWindowUnminimized(unsigned handle);
void OnCommit(unsigned handle, std::string text);
void OnPreeditChanged(unsigned handle, std::string text, std::string commit);
void OnPreeditEnd();
dispatcher->WindowResized(window->Handle(), width, height);
}
+void WaylandShellSurface::WindowActivated(void *data) {
+ WaylandWindow *window = static_cast<WaylandWindow*>(data);
+ WaylandShellSurface* shellSurface = window->ShellSurface();
+
+ if (shellSurface->IsMinimized()) {
+ shellSurface->Unminimize();
+
+ ui::EventConverterOzoneWayland* dispatcher =
+ ui::EventFactoryOzoneWayland::GetInstance()->EventConverter();
+ dispatcher->WindowUnminimized(window->Handle());
+ }
+}
+
} // namespace ozonewayland
virtual void SetWindowTitle(const base::string16& title) = 0;
virtual void Maximize() = 0;
virtual void Minimize() = 0;
+ virtual void Unminimize() = 0;
+ virtual bool IsMinimized() const = 0;
// static functions.
static void PopupDone();
static void WindowResized(void *data, unsigned width, unsigned height);
+ static void WindowActivated(void *data);
protected:
void FlushDisplay() const;
void WLShellSurface::Minimize() {
}
+void WLShellSurface::Unminimize() {
+}
+
+bool WLShellSurface::IsMinimized() const {
+ return false;
+}
+
void WLShellSurface::HandleConfigure(void* data,
struct wl_shell_surface* surface,
uint32_t edges,
virtual void SetWindowTitle(const base::string16& title) OVERRIDE;
virtual void Maximize() OVERRIDE;
virtual void Minimize() OVERRIDE;
+ virtual void Unminimize() OVERRIDE;
+ virtual bool IsMinimized() const OVERRIDE;
static void HandleConfigure(void* data,
struct wl_shell_surface* shell_surface,
: WaylandShellSurface(),
xdg_surface_(NULL),
xdg_popup_(NULL),
- maximized_(false) {
+ maximized_(false),
+ minimized_(false) {
}
XDGShellSurface::~XDGShellSurface() {
void XDGShellSurface::Minimize() {
xdg_surface_set_minimized(xdg_surface_);
+ minimized_ = true;
+}
+
+void XDGShellSurface::Unminimize() {
+ minimized_ = false;
+}
+
+bool XDGShellSurface::IsMinimized() const {
+ return minimized_;
}
void XDGShellSurface::HandleConfigure(void* data,
void XDGShellSurface::HandleActivate(void* data,
struct xdg_surface* xdg_surface) {
+ WaylandShellSurface::WindowActivated(data);
}
void XDGShellSurface::HandleDeactivate(void* data,
virtual void SetWindowTitle(const base::string16& title) OVERRIDE;
virtual void Maximize() OVERRIDE;
virtual void Minimize() OVERRIDE;
+ virtual void Unminimize() OVERRIDE;
+ virtual bool IsMinimized() const OVERRIDE;
static void HandleConfigure(void* data,
struct xdg_surface* xdg_surface,
xdg_surface* xdg_surface_;
xdg_popup* xdg_popup_;
bool maximized_;
+ bool minimized_;
DISALLOW_COPY_AND_ASSIGN(XDGShellSurface);
};
#ifndef _VA_H_
#define _VA_H_
+#include <stddef.h>
#include <stdint.h>
#include <va/va_version.h>
VABufferID buffer_id
);
+/** VA buffer information */
+typedef struct {
+ /** Buffer handle */
+ uintptr_t handle;
+ /** Buffer type (See VABufferType). */
+ uint32_t type;
+ /**
+ * Buffer memory type (See VASurfaceAttribMemoryType).
+ *
+ * On input to vaLockBuffer(), this field can serve as a hint to
+ * specify the set of memory types the caller is interested in. On
+ * successful return from vaLockBuffer(), the field is updated
+ * with the best matching memory type.
+ */
+ uint32_t mem_type;
+ /** Size of the underlying buffer. */
+ size_t mem_size;
+} VABufferInfo;
+
+/**
+ * Locks buffer for external API usage.
+ *
+ * Locks the VA buffer object buf_id for external API usage like
+ * EGL or OpenCL (OCL). This function is a synchronization point. This
+ * means that any pending operation is guaranteed to be completed
+ * prior to returning from the function.
+ *
+ * If the referenced VA buffer object is the backing store of a VA
+ * surface, then this function acts as if vaSyncSurface() on the
+ * parent surface was called first.
+ *
+ * The VABufferInfo argument shall be zero'ed on input. On
+ * successful output, the data structure is filled in with all the
+ * necessary buffer level implementation details like handle, type,
+ * memory type and memory size.
+ *
+ * Note: the external API implementation, or the application, can
+ * express the memory types it is interested in by filling in the
+ * mem_type field accordingly. On successful output, the memory type
+ * that fits best the request and that was used is updated in the
+ * VABufferInfo data structure. If none of the supplied memory types
+ * is supported, then a VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
+ * error is returned.
+ *
+ * The VABufferInfo data is valid until vaUnlockBuffer() is
+ * called. Besides, no additional operation is allowed on any of the
+ * buffer parent object until vaUnlockBuffer() is called. e.g. decoding
+ * into a VA surface backed with the supplied VA buffer object
+ * buf_id would fail with a VA_STATUS_ERROR_SURFACE_BUSY error.
+ *
+ * Possible errors:
+ * - VA_STATUS_ERROR_UNIMPLEMENTED: the VA driver implementation
+ * does not support this interface
+ * - VA_STATUS_ERROR_INVALID_DISPLAY: an invalid display was supplied
+ * - VA_STATUS_ERROR_INVALID_BUFFER: an invalid buffer was supplied
+ * - VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE: the implementation
+ * does not support exporting buffers of the specified type
+ * - VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE: none of the requested
+ * memory types in \ref VABufferInfo.mem_type was supported
+ *
+ * @param[in] dpy the VA display
+ * @param[in] buf_id the VA buffer
+ * @param[in,out] buf_info_ptr the VA buffer information
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus
+vaLockBuffer(
+ VADisplay dpy,
+ VABufferID buf_id,
+ VABufferInfo * buf_info_ptr
+);
+
+/**
+ * Unlocks buffer after usage from external API.
+ *
+ * Unlocks the VA buffer object buf_id from external API usage like
+ * EGL or OpenCL (OCL). This function is a synchronization point. This
+ * means that any pending operation is guaranteed to be completed
+ * prior to returning from the function.
+ *
+ * The VABufferInfo argument shall point to the original data
+ * structure that was obtained from vaLockBuffer(), unaltered. This is
+ * necessary so that the VA driver implementation could deallocate any
+ * resources that were needed.
+ *
+ * In any case, returning from this function invalidates any contents
+ * in VABufferInfo. i.e. the underlyng buffer handle is no longer
+ * valid. Therefore, VA driver implementations are free to reset this
+ * data structure to safe defaults.
+ *
+ * Possible errors:
+ * - VA_STATUS_ERROR_UNIMPLEMENTED: the VA driver implementation
+ * does not support this interface
+ * - VA_STATUS_ERROR_INVALID_DISPLAY: an invalid display was supplied
+ * - VA_STATUS_ERROR_INVALID_BUFFER: an invalid buffer was supplied
+ * - VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE: the implementation
+ * does not support exporting buffers of the specified type
+ *
+ * @param[in] dpy the VA display
+ * @param[in] buf_id the VA buffer
+ * @param[in,out] buf_info_ptr the VA buffer information
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus
+vaUnlockBuffer(
+ VADisplay dpy,
+ VABufferID buf_id,
+ VABufferInfo * buf_info_ptr
+);
+
/*
Render (Decode) Pictures
VASurfaceAttrib *attrib_list,
unsigned int *num_attribs
);
+
+ VAStatus
+ (*vaLockBuffer)(
+ VADriverContextP ctx,
+ VABufferID buf_id,
+ VABufferInfo * buf_info_ptr
+ );
+
+ VAStatus
+ (*vaUnlockBuffer)(
+ VADriverContextP ctx,
+ VABufferID buf_id,
+ VABufferInfo * buf_info_ptr
+ );
};
struct VADriverContext
*/
class V8_EXPORT CpuProfileNode {
public:
+ struct LineTick {
+ /** The 1-based number of the source line where the function originates. */
+ int line;
+
+ /** The count of samples associated with the source line. */
+ unsigned int hit_count;
+ };
+
/** Returns function name (empty string for anonymous functions.) */
Handle<String> GetFunctionName() const;
*/
int GetColumnNumber() const;
+ /**
+ * Returns the number of the function's source lines that collect the samples.
+ */
+ unsigned int GetHitLineCount() const;
+
+ /** Returns the set of source lines that collect the samples.
+ * The caller allocates buffer and responsible for releasing it.
+ * True if all available entries are copied, otherwise false.
+ * The function copies nothing if buffer is not large enough.
+ */
+ bool GetLineTicks(LineTick* entries, unsigned int length) const;
+
/** Returns bailout reason for the function
* if the optimization was disabled for it.
*/
}
+unsigned int CpuProfileNode::GetHitLineCount() const {
+ const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+ return node->GetHitLineCount();
+}
+
+
+bool CpuProfileNode::GetLineTicks(LineTick* entries,
+ unsigned int length) const {
+ const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+ return node->GetLineTicks(entries, length);
+}
+
+
const char* CpuProfileNode::GetBailoutReason() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
return node->entry()->bailout_reason();
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->start = code->address();
+ Script* script = NULL;
+ JITLineInfoTable* line_table = NULL;
+ if (shared->script()->IsScript()) {
+ DCHECK(Script::cast(shared->script()));
+ script = Script::cast(shared->script());
+ line_table = new JITLineInfoTable();
+ for (RelocIterator it(code); !it.done(); it.next()) {
+ RelocInfo::Mode mode = it.rinfo()->rmode();
+ if (RelocInfo::IsPosition(mode)) {
+ int position = static_cast<int>(it.rinfo()->data());
+ if (position >= 0) {
+ int pc_offset = static_cast<int>(it.rinfo()->pc() - code->address());
+ int line_number = script->GetLineNumber(position) + 1;
+ line_table->SetPosition(pc_offset, line_number);
+ }
+ }
+ }
+ }
rec->entry = profiles_->NewCodeEntry(
tag, profiles_->GetFunctionName(shared->DebugName()),
CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), line,
- column);
+ column, line_table);
if (info) {
rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
}
- DCHECK(Script::cast(shared->script()));
- Script* script = Script::cast(shared->script());
- rec->entry->set_script_id(script->id()->value());
- rec->size = code->ExecutableSize();
- rec->shared = shared->address();
+ if (script) {
+ rec->entry->set_script_id(script->id()->value());
+ }
rec->entry->set_bailout_reason(
GetBailoutReason(shared->DisableOptimizationReason()));
+ rec->size = code->ExecutableSize();
+ rec->shared = shared->address();
processor_->Enqueue(evt_rec);
}
void FullCodeGenerator::SetSourcePosition(int pos) {
if (pos != RelocInfo::kNoPosition) {
masm_->positions_recorder()->RecordPosition(pos);
+ masm_->positions_recorder()->WriteRecordedPositions();
}
}
const char* name_prefix,
const char* resource_name,
int line_number,
- int column_number)
+ int column_number,
+ JITLineInfoTable* line_info)
: tag_(tag),
builtin_id_(Builtins::builtin_count),
name_prefix_(name_prefix),
shared_id_(0),
script_id_(v8::UnboundScript::kNoScriptId),
no_frame_ranges_(NULL),
- bailout_reason_(kEmptyBailoutReason) { }
+ bailout_reason_(kEmptyBailoutReason),
+ line_info_(line_info) { }
bool CodeEntry::is_js_function_tag(Logger::LogEventsAndTags tag) {
}
+static bool LineTickMatch(void* a, void* b) {
+ return a == b;
+}
+
+
ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry)
: tree_(tree),
entry_(entry),
self_ticks_(0),
children_(CodeEntriesMatch),
- id_(tree->next_node_id()) { }
+ id_(tree->next_node_id()),
+ line_ticks_(LineTickMatch) { }
} } // namespace v8::internal
CodeEntry::~CodeEntry() {
delete no_frame_ranges_;
+ delete line_info_;
}
}
+int CodeEntry::GetSourceLine(int pc_offset) const {
+ if (line_info_ && !line_info_->Empty()) {
+ return line_info_->GetSourceLineNumber(pc_offset);
+ }
+ return v8::CpuProfileNode::kNoLineNumberInfo;
+}
+
+
ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
HashMap::Entry* map_entry =
children_.Lookup(entry, CodeEntryHash(entry), false);
}
+void ProfileNode::IncrementLineTicks(int src_line) {
+ if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) return;
+ // Increment a hit counter of a certain source line.
+ // Add a new source line if not found.
+ HashMap::Entry* e =
+ line_ticks_.Lookup(reinterpret_cast<void*>(src_line), src_line, true);
+ DCHECK(e);
+ e->value = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(e->value) + 1);
+}
+
+
+bool ProfileNode::GetLineTicks(v8::CpuProfileNode::LineTick* entries,
+ unsigned int length) const {
+ if (entries == NULL || length == 0) return false;
+
+ unsigned line_count = line_ticks_.occupancy();
+
+ if (line_count == 0) return false;
+ if (length < line_count) return false;
+
+ v8::CpuProfileNode::LineTick* entry = entries;
+
+ for (HashMap::Entry* p = line_ticks_.Start();
+ p != NULL;
+ p = line_ticks_.Next(p), entry++) {
+ entry->line =
+ static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->key));
+ entry->hit_count =
+ static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->value));
+ }
+
+ return true;
+}
+
+
void ProfileNode::Print(int indent) {
base::OS::Print("%5u %*s %s%s %d #%d %s", self_ticks_, indent, "",
entry_->name_prefix(), entry_->name(), entry_->script_id(),
}
-ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
+ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path,
+ int src_line) {
ProfileNode* node = root_;
for (CodeEntry** entry = path.start() + path.length() - 1;
entry != path.start() - 1;
}
}
node->IncrementSelfTicks();
+ if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) {
+ node->IncrementLineTicks(src_line);
+ }
return node;
}
-void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path) {
+void ProfileTree::AddPathFromStart(const Vector<CodeEntry*>& path,
+ int src_line) {
ProfileNode* node = root_;
for (CodeEntry** entry = path.start();
entry != path.start() + path.length();
}
}
node->IncrementSelfTicks();
+ if (src_line != v8::CpuProfileNode::kNoLineNumberInfo) {
+ node->IncrementLineTicks(src_line);
+ }
}
void CpuProfile::AddPath(base::TimeTicks timestamp,
- const Vector<CodeEntry*>& path) {
- ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path);
+ const Vector<CodeEntry*>& path,
+ int src_line) {
+ ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path, src_line);
if (record_samples_) {
timestamps_.Add(timestamp);
samples_.Add(top_frame_node);
void CpuProfilesCollection::AddPathToCurrentProfiles(
- base::TimeTicks timestamp, const Vector<CodeEntry*>& path) {
+ base::TimeTicks timestamp,
+ const Vector<CodeEntry*>& path,
+ int src_line) {
// As starting / stopping profiles is rare relatively to this
// method, we don't bother minimizing the duration of lock holding,
// e.g. copying contents of the list to a local vector.
current_profiles_semaphore_.Wait();
for (int i = 0; i < current_profiles_.length(); ++i) {
- current_profiles_[i]->AddPath(timestamp, path);
+ current_profiles_[i]->AddPath(timestamp, path, src_line);
}
current_profiles_semaphore_.Signal();
}
const char* name_prefix,
const char* resource_name,
int line_number,
- int column_number) {
+ int column_number,
+ JITLineInfoTable* line_info) {
CodeEntry* code_entry = new CodeEntry(tag,
name,
name_prefix,
resource_name,
line_number,
- column_number);
+ column_number,
+ line_info);
code_entries_.Add(code_entry);
return code_entry;
}
// entries vector with NULL values.
CodeEntry** entry = entries.start();
memset(entry, 0, entries.length() * sizeof(*entry));
+
+ // The ProfileNode knows nothing about all versions of generated code for
+ // the same JS function. The line number information associated with
+ // the latest version of generated code is used to find a source line number
+ // for a JS function. Then, the detected source line is passed to
+ // ProfileNode to accumulate the samples.
+ int src_line = v8::CpuProfileNode::kNoLineNumberInfo;
+
if (sample.pc != NULL) {
if (sample.has_external_callback && sample.state == EXTERNAL &&
sample.top_frame_type == StackFrame::EXIT) {
// frame. Check for this case and just skip such samples.
if (pc_entry) {
List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
+ Code* code = Code::cast(HeapObject::FromAddress(start));
+ int pc_offset = static_cast<int>(sample.pc - code->instruction_start());
+ src_line = pc_entry->GetSourceLine(pc_offset);
if (ranges) {
- Code* code = Code::cast(HeapObject::FromAddress(start));
- int pc_offset = static_cast<int>(
- sample.pc - code->instruction_start());
for (int i = 0; i < ranges->length(); i++) {
OffsetRange& range = ranges->at(i);
if (range.from <= pc_offset && pc_offset < range.to) {
}
}
+ bool src_line_not_found = src_line == v8::CpuProfileNode::kNoLineNumberInfo;
+
for (const Address* stack_pos = sample.stack,
*stack_end = stack_pos + sample.frames_count;
stack_pos != stack_end;
++stack_pos) {
- *entry++ = code_map_.FindEntry(*stack_pos);
+ Address start = NULL;
+ *entry = code_map_.FindEntry(*stack_pos, &start);
+
+ // Skip unresolved frames (e.g. internal frame) and get source line of
+ // the JS caller.
+ if (src_line_not_found && *entry) {
+ Code* code = Code::cast(HeapObject::FromAddress(start));
+ int pc_offset =
+ static_cast<int>(*stack_pos - code->instruction_start());
+ src_line = (*entry)->GetSourceLine(pc_offset);
+ if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
+ src_line = (*entry)->line_number();
+ }
+ src_line_not_found = false;
+ }
+
+ entry++;
}
}
}
}
- profiles_->AddPathToCurrentProfiles(sample.timestamp, entries);
+ profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line);
}
#ifndef V8_PROFILE_GENERATOR_H_
#define V8_PROFILE_GENERATOR_H_
+#include <map>
#include "include/v8-profiler.h"
#include "src/allocation.h"
#include "src/hashmap.h"
};
+// Provides a mapping from the offsets within generated code to
+// the source line.
+class JITLineInfoTable : public Malloced {
+ public:
+ JITLineInfoTable() {}
+ ~JITLineInfoTable() {}
+
+ void SetPosition(int pc_offset, int line) {
+ DCHECK(pc_offset >= 0);
+ DCHECK(line > 0); // The 1-based number of the source line.
+ pc_offset_map_.insert(std::make_pair(pc_offset, line));
+ }
+
+ int GetSourceLineNumber(int pc_offset) const {
+ PcOffsetMap::const_iterator it = pc_offset_map_.lower_bound(pc_offset);
+ if (it == pc_offset_map_.end()) {
+ return v8::CpuProfileNode::kNoLineNumberInfo;
+ }
+ return it->second;
+ }
+
+ bool Empty() const { return pc_offset_map_.empty(); }
+
+ private:
+ // pc_offset -> source line
+ typedef std::map<int, int> PcOffsetMap;
+ PcOffsetMap pc_offset_map_;
+ DISALLOW_COPY_AND_ASSIGN(JITLineInfoTable);
+};
+
class CodeEntry {
public:
// CodeEntry doesn't own name strings, just references them.
const char* name_prefix = CodeEntry::kEmptyNamePrefix,
const char* resource_name = CodeEntry::kEmptyResourceName,
int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
- int column_number = v8::CpuProfileNode::kNoColumnNumberInfo);
+ int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
+ JITLineInfoTable* line_info = NULL);
~CodeEntry();
bool is_js_function() const { return is_js_function_tag(tag_); }
const char* resource_name() const { return resource_name_; }
int line_number() const { return line_number_; }
int column_number() const { return column_number_; }
+ const JITLineInfoTable* line_info() const { return line_info_; }
void set_shared_id(int shared_id) { shared_id_ = shared_id; }
int script_id() const { return script_id_; }
void set_script_id(int script_id) { script_id_ = script_id; }
uint32_t GetCallUid() const;
bool IsSameAs(CodeEntry* entry) const;
+ int GetSourceLine(int pc_offset) const;
+
static const char* const kEmptyNamePrefix;
static const char* const kEmptyResourceName;
static const char* const kEmptyBailoutReason;
int script_id_;
List<OffsetRange>* no_frame_ranges_;
const char* bailout_reason_;
+ JITLineInfoTable* line_info_;
DISALLOW_COPY_AND_ASSIGN(CodeEntry);
};
ProfileNode* FindOrAddChild(CodeEntry* entry);
void IncrementSelfTicks() { ++self_ticks_; }
void IncreaseSelfTicks(unsigned amount) { self_ticks_ += amount; }
+ void IncrementLineTicks(int src_line);
CodeEntry* entry() const { return entry_; }
unsigned self_ticks() const { return self_ticks_; }
const List<ProfileNode*>* children() const { return &children_list_; }
unsigned id() const { return id_; }
+ unsigned int GetHitLineCount() const { return line_ticks_.occupancy(); }
+ bool GetLineTicks(v8::CpuProfileNode::LineTick* entries,
+ unsigned int length) const;
void Print(int indent);
HashMap children_;
List<ProfileNode*> children_list_;
unsigned id_;
+ HashMap line_ticks_;
DISALLOW_COPY_AND_ASSIGN(ProfileNode);
};
ProfileTree();
~ProfileTree();
- ProfileNode* AddPathFromEnd(const Vector<CodeEntry*>& path);
- void AddPathFromStart(const Vector<CodeEntry*>& path);
+ ProfileNode* AddPathFromEnd(
+ const Vector<CodeEntry*>& path,
+ int src_line = v8::CpuProfileNode::kNoLineNumberInfo);
+ void AddPathFromStart(const Vector<CodeEntry*>& path,
+ int src_line = v8::CpuProfileNode::kNoLineNumberInfo);
ProfileNode* root() const { return root_; }
unsigned next_node_id() { return next_node_id_++; }
CpuProfile(const char* title, bool record_samples);
// Add pc -> ... -> main() call path to the profile.
- void AddPath(base::TimeTicks timestamp, const Vector<CodeEntry*>& path);
+ void AddPath(base::TimeTicks timestamp,
+ const Vector<CodeEntry*>& path,
+ int src_line);
void CalculateTotalTicksAndSamplingRate();
const char* title() const { return title_; }
const char* name_prefix = CodeEntry::kEmptyNamePrefix,
const char* resource_name = CodeEntry::kEmptyResourceName,
int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
- int column_number = v8::CpuProfileNode::kNoColumnNumberInfo);
+ int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
+ JITLineInfoTable* line_info = NULL);
// Called from profile generator thread.
- void AddPathToCurrentProfiles(
- base::TimeTicks timestamp, const Vector<CodeEntry*>& path);
+ void AddPathToCurrentProfiles(base::TimeTicks timestamp,
+ const Vector<CodeEntry*>& path,
+ int src_line);
// Limits the number of profiles that can be simultaneously collected.
static const int kMaxSimultaneousProfiles = 100;
}
+// This tests checks distribution of the samples through the source lines.
+TEST(TickLines) {
+ CcTest::InitializeVM();
+ LocalContext env;
+ i::Isolate* isolate = CcTest::i_isolate();
+ i::Factory* factory = isolate->factory();
+ i::HandleScope scope(isolate);
+
+ i::EmbeddedVector<char, 512> script;
+
+ const char* func_name = "func";
+ i::SNPrintF(script,
+ "function %s() {\n"
+ " for (var i = 0; i < 10; ++i) {\n"
+ " var n = 0;\n"
+ " var m = 100*100;\n"
+ " while (m > 1) {\n"
+ " m--;\n"
+ " n += m * m * m;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "%s();\n", func_name, func_name);
+
+ CompileRun(script.start());
+
+ i::Handle<i::JSFunction> func = v8::Utils::OpenHandle(
+ *v8::Local<v8::Function>::Cast(
+ (*env)->Global()->Get(v8_str(func_name))));
+ CHECK_NE(NULL, func->shared());
+ CHECK_NE(NULL, func->shared()->code());
+ i::Code* code = NULL;
+ if (func->code()->is_optimized_code()) {
+ code = func->code();
+ } else {
+ CHECK(func->shared()->code() == func->code() || !i::FLAG_crankshaft);
+ code = func->shared()->code();
+ }
+ CHECK_NE(NULL, code);
+ i::Address code_address = code->address();
+ CHECK_NE(NULL, code_address);
+
+ CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
+ profiles->StartProfiling("", false);
+ ProfileGenerator generator(profiles);
+ SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
+ &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
+ processor->Start();
+ CpuProfiler profiler(isolate, profiles, &generator, processor.get());
+
+ // Enqueue code creation events.
+ i::Handle<i::String> str = factory->NewStringFromAsciiChecked(func_name);
+ int line = 1;
+ int column = 1;
+ profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG,
+ code,
+ func->shared(),
+ NULL,
+ *str,
+ line,
+ column);
+
+ // Enqueue a tick event to enable code events processing.
+ EnqueueTickSampleEvent(processor.get(), code_address);
+
+ processor->StopSynchronously();
+
+ CpuProfile* profile = profiles->StopProfiling("");
+ CHECK_NE(NULL, profile);
+
+ // Check the state of profile generator.
+ CodeEntry* func_entry = generator.code_map()->FindEntry(code_address);
+ CHECK_NE(NULL, func_entry);
+ CHECK_EQ(func_name, func_entry->name());
+ const i::JITLineInfoTable* line_info = func_entry->line_info();
+ CHECK_NE(NULL, line_info);
+ CHECK_EQ(false, line_info->Empty());
+
+ // Check the hit source lines using V8 Public APIs.
+ const i::ProfileTree* tree = profile->top_down();
+ ProfileNode* root = tree->root();
+ CHECK_NE(NULL, root);
+ ProfileNode* func_node = root->FindChild(func_entry);
+ CHECK_NE(NULL, func_node);
+
+ // Add 10 faked ticks to source line #5.
+ int hit_line = 5;
+ int hit_count = 10;
+ for (int i = 0; i < hit_count; i++)
+ func_node->IncrementLineTicks(hit_line);
+
+ unsigned int line_count = func_node->GetHitLineCount();
+ CHECK_EQ(2, line_count); // Expect two hit source lines - #1 and #5.
+ ScopedVector<v8::CpuProfileNode::LineTick> entries(line_count);
+ CHECK_EQ(true, func_node->GetLineTicks(&entries[0], line_count));
+ int value = 0;
+ for (int i = 0; i < entries.length(); i++)
+ if (entries[i].line == hit_line) {
+ value = entries[i].hit_count;
+ break;
+ }
+ CHECK_EQ(hit_count, value);
+}
+
+
static const char* call_function_test_source = "function bar(iterations) {\n"
"}\n"
"function start(duration) {\n"
# Edit these when rolling DEPS.xwalk.
# -----------------------------------
-chromium_crosswalk_rev = 'e5698a22dd1587355fd53fa7142be15776985608'
+chromium_crosswalk_rev = '04ba13a65546e6e6309e560b9a2491b904ed57a8'
blink_crosswalk_rev = '92e5d6adee53362b3f5aaec11bcb0526d5f0715d'
-v8_crosswalk_rev = '0bb343f5ed1becef0996a234d5d7d431e60ef72a'
-ozone_wayland_rev = 'db2f41907a6c63f8c1dfc100f4db4ce5b2259a76'
+v8_crosswalk_rev = '6264ffa1bef0681640afbafb5194c55a172ef6df'
+ozone_wayland_rev = 'd301e5c546a7dea0de8fde5b07a2a57afd02103b'
crosswalk_git = 'https://github.com/crosswalk-project'
ozone_wayland_git = 'https://github.com/01org'
MAJOR=9
MINOR=38
-BUILD=198
+BUILD=204
PATCH=0
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.xwalk.app.hello.world">
- <application android:name="org.xwalk.app.runtime.XWalkRuntimeApplication"
+ <application android:name="org.xwalk.core.XWalkApplication"
android:label="XWalkAppHelloWorld" android:hardwareAccelerated="true"
android:icon="@drawable/crosswalk">
<activity android:name="org.xwalk.app.hello.world.HelloWorldActivity"
package="org.xwalk.app.template"
android:installLocation="auto">
- <application android:name="org.xwalk.app.runtime.XWalkRuntimeApplication"
+ <application android:name="org.xwalk.core.XWalkApplication"
android:label="XWalkAppTemplate" android:hardwareAccelerated="true"
android:icon="@drawable/crosswalk">
<activity android:name="org.xwalk.app.template.AppTemplateActivity"
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
-import android.widget.Toast;
-import org.xwalk.app.runtime.CrossPackageWrapper;
-import org.xwalk.app.runtime.CrossPackageWrapperExceptionHandler;
-import org.xwalk.app.runtime.XWalkRuntimeClient;
+import org.xwalk.app.runtime.extension.XWalkRuntimeExtensionManager;
import org.xwalk.app.runtime.XWalkRuntimeLibraryException;
+import org.xwalk.app.runtime.XWalkRuntimeView;
+import org.xwalk.core.ReflectionHelper;
+import org.xwalk.core.XWalkPreferences;
-public abstract class XWalkRuntimeActivityBase extends Activity implements CrossPackageWrapperExceptionHandler {
+public abstract class XWalkRuntimeActivityBase extends Activity {
private static final String DEFAULT_LIBRARY_APK_URL = null;
- private XWalkRuntimeClient mRuntimeView;
+ private XWalkRuntimeView mRuntimeView;
private boolean mShownNotFoundDialog = false;
private AlertDialog mLibraryNotFoundDialog = null;
+ private XWalkRuntimeExtensionManager mExtensionManager;
+
@Override
public void onCreate(Bundle savedInstanceState) {
IntentFilter intentFilter = new IntentFilter("org.xwalk.intent");
if (bundle.containsKey("remotedebugging")) {
String extra = bundle.getString("remotedebugging");
if (extra.equals("true")) {
- String mPackageName = getApplicationContext().getPackageName();
- mRuntimeView.enableRemoteDebugging("", mPackageName);
+ XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);
} else if (extra.equals("false")) {
- mRuntimeView.disableRemoteDebugging();
+ XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, false);
}
}
}
registerReceiver(mReceiver, intentFilter);
super.onCreate(savedInstanceState);
tryLoadRuntimeView();
- mRuntimeView.onCreate();
+ if (mRuntimeView != null) mRuntimeView.onCreate();
}
@Override
public void onStart() {
super.onStart();
- tryLoadRuntimeView();
- mRuntimeView.onStart();
+ if (mExtensionManager != null) mExtensionManager.onStart();
}
@Override
public void onPause() {
super.onPause();
- mRuntimeView.onPause();
+ if (mRuntimeView != null) mRuntimeView.onPause();
+ if (mExtensionManager != null) mExtensionManager.onPause();
}
@Override
public void onResume() {
super.onResume();
- mRuntimeView.onResume();
+ if (mRuntimeView != null) mRuntimeView.onResume();
+ if (mExtensionManager != null) mExtensionManager.onResume();
}
@Override
public void onStop() {
super.onStop();
- mRuntimeView.onStop();
+ if (mExtensionManager != null) mExtensionManager.onStop();
}
@Override
public void onDestroy() {
unregisterReceiver(mReceiver);
+ if (mExtensionManager != null) mExtensionManager.onDestroy();
super.onDestroy();
- mRuntimeView.onDestroy();
}
@Override
public void onNewIntent(Intent intent) {
- if (!mRuntimeView.onNewIntent(intent)) super.onNewIntent(intent);
+ if (mRuntimeView == null || !mRuntimeView.onNewIntent(intent)) super.onNewIntent(intent);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- mRuntimeView.onActivityResult(requestCode, resultCode, data);
+ if (mRuntimeView != null) mRuntimeView.onActivityResult(requestCode, resultCode, data);
+ if (mExtensionManager != null) mExtensionManager.onActivityResult(requestCode, resultCode, data);
}
private String getLibraryApkDownloadUrl() {
}
private void tryLoadRuntimeView() {
- if (mRuntimeView == null || mRuntimeView.get() == null) {
- mRuntimeView = new XWalkRuntimeClient(this, null, this);
- if (mRuntimeView.get() != null) {
- mShownNotFoundDialog = false;
- if (mLibraryNotFoundDialog != null) mLibraryNotFoundDialog.cancel();
- }
+ try {
+ mRuntimeView = new XWalkRuntimeView(this, this, null);
+ mShownNotFoundDialog = false;
+ if (mLibraryNotFoundDialog != null) mLibraryNotFoundDialog.cancel();
if (mRemoteDebugging) {
- String mPackageName = getApplicationContext().getPackageName();
- mRuntimeView.enableRemoteDebugging("", mPackageName);
+ XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);
} else {
- mRuntimeView.disableRemoteDebugging();
+ XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, false);
}
-
- didTryLoadRuntimeView(mRuntimeView.get());
+ // XWalkPreferences.ENABLE_EXTENSIONS
+ if (XWalkPreferences.getValue("enable-extensions")) {
+ // Enable xwalk extension mechanism and start load extensions here.
+ // Note that it has to be after above initialization.
+ mExtensionManager = new XWalkRuntimeExtensionManager(getApplicationContext(), this);
+ mExtensionManager.loadExtensions();
+ }
+ } catch (Exception e) {
+ handleException(e);
}
+ didTryLoadRuntimeView(mRuntimeView);
}
- public XWalkRuntimeClient getRuntimeView() {
+ public XWalkRuntimeView getRuntimeView() {
return mRuntimeView;
}
- @Override
- public void onException(Exception e) {
- if (e.getClass() == XWalkRuntimeLibraryException.class) {
+ public void handleException(Throwable e) {
+ if (e instanceof RuntimeException) {
+ handleException(e.getCause());
+ return;
+ }
+
+ if (e instanceof XWalkRuntimeLibraryException) {
String title = "";
String message = "";
XWalkRuntimeLibraryException runtimeException = (XWalkRuntimeLibraryException) e;
case XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_INVOKE_FAILED:
default:
Exception originException = runtimeException.getOriginException();
- if (originException != null) onException(originException);
+ if (originException != null) handleException(originException);
return;
}
showRuntimeLibraryExceptionDialog(title, message);
} else {
e.printStackTrace();
- onException(e.getLocalizedMessage());
throw new RuntimeException(e);
}
}
- @Override
- public void onException(String message) {
- Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
- }
-
private void showRuntimeLibraryExceptionDialog(String title, String message) {
if (!mShownNotFoundDialog) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
- if (XWalkRuntimeClient.libraryIsEmbedded()) {
+ if (!ReflectionHelper.shouldUseLibrary()) {
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
public void onClick(DialogInterface dialog, int id) {
Intent goToMarket = new Intent(Intent.ACTION_VIEW);
goToMarket.setData(Uri.parse(
- "market://details?id="+CrossPackageWrapper.LIBRARY_APK_PACKAGE_NAME));
+ "market://details?id=org.xwalk.core"));
startActivity(goToMarket);
}
});
+++ /dev/null
-// 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.app.runtime;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-public abstract class CrossPackageWrapper {
- public final static String LIBRARY_APK_PACKAGE_NAME = "org.xwalk.runtime.lib";
- private Context mLibCtx;
- private Class<?> mTargetClass;
- private Constructor<?> mCreator;
- private CrossPackageWrapperExceptionHandler mExceptionHandler;
- private static boolean sLibraryEmbedded = true;
-
- public CrossPackageWrapper(Context ctx, String className,
- CrossPackageWrapperExceptionHandler handler, Class<?>... parameters) {
- try {
- mTargetClass = ctx.getClassLoader().loadClass(className);
- sLibraryEmbedded = true;
- } catch (ClassNotFoundException e) {
- sLibraryEmbedded = false;
- }
- mExceptionHandler = handler;
- try {
- if (sLibraryEmbedded) {
- mLibCtx = ctx;
- } else {
- mLibCtx = ctx.createPackageContext(
- LIBRARY_APK_PACKAGE_NAME,
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
- Context app = ctx.getApplicationContext();
- assert(app instanceof XWalkRuntimeApplication);
- XWalkRuntimeApplication xwalkApp = (XWalkRuntimeApplication) app;
- xwalkApp.addResource(mLibCtx.getResources());
-
- mTargetClass =
- mLibCtx.getClassLoader().loadClass(className);
- }
- mCreator = mTargetClass.getConstructor(parameters);
- } catch (NameNotFoundException e) {
- handleException(e);
- } catch (ClassNotFoundException e) {
- handleException(e);
- } catch (NoSuchMethodException e) {
- handleException(e);
- }
- }
-
- public Object createInstance(Object... parameters) {
- Object ret = null;
- if (mCreator != null) {
- try {
- ret = mCreator.newInstance(parameters);
- } catch (IllegalArgumentException e) {
- handleException(e);
- } catch (InstantiationException e) {
- handleException(e);
- } catch (IllegalAccessException e) {
- handleException(e);
- } catch (InvocationTargetException e) {
- handleException(e);
- }
- }
- return ret;
- }
-
- public void handleException(Exception e) {
- if (mExceptionHandler != null) mExceptionHandler.onException(e);
- }
-
- public void handleException(String e) {
- if (mExceptionHandler != null) mExceptionHandler.onException(e);
- }
-
- public Class<?> getTargetClass() {
- return mTargetClass;
- }
-
- public Context getLibraryContext() {
- return mLibCtx;
- }
-
- public Method lookupMethod(String method, Class<?>... parameters) {
- if (mTargetClass == null) return null;
- try {
- return mTargetClass.getMethod(method, parameters);
- } catch (NoSuchMethodException e) {
- handleException(e);
- }
- return null;
- }
-
- public Object invokeMethod(Method m, Object instance, Object... parameters) {
- Object ret = null;
- if (m != null) {
- try {
- ret = m.invoke(instance, parameters);
- } catch (IllegalArgumentException e) {
- handleException(e);
- } catch (IllegalAccessException e) {
- handleException(e);
- } catch (InvocationTargetException e) {
- handleException(e);
- } catch (NullPointerException e) {
- handleException(e);
- }
- }
- return ret;
- }
-
- public static boolean libraryIsEmbedded() {
- return sLibraryEmbedded;
- }
-}
+++ /dev/null
-// 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.app.runtime;
-
-public interface CrossPackageWrapperExceptionHandler {
- public void onException(Exception e);
- public void onException(String msg);
-}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.runtime;
+package org.xwalk.app.runtime;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.widget.FrameLayout;
+import org.xwalk.core.SharedXWalkExceptionHandler;
+import org.xwalk.core.SharedXWalkView;
import org.xwalk.core.XWalkView;
import org.xwalk.core.XWalkPreferences;
private void init(Context context, Activity activity) {
// TODO(yongsheng): do customizations for XWalkView. There will
// be many callback classes which are needed to be implemented.
- mXWalkView = new XWalkView(context, activity);
+ mXWalkView = new SharedXWalkView(context, activity, new SharedXWalkExceptionHandler() {
+ @Override
+ public void onSharedLibraryNotFound() {
+ throw new RuntimeException(new XWalkRuntimeLibraryException(
+ XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_NOT_INSTALLED));
+ }
+ });
}
@Override
}
@Override
- public void onStart() {
- }
-
- @Override
public void onResume() {
}
}
@Override
- public void onStop() {
- }
-
- @Override
public void onDestroy() {
}
+++ /dev/null
-// 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.app.runtime;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import java.lang.reflect.Method;
-import java.util.StringTokenizer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * This class is to encapsulate the reflection detail of
- * invoking XWalkRuntimeView class in library APK.
- *
- * A web application APK should use this class in its Activity.
- */
-public class XWalkRuntimeClient extends CrossPackageWrapper {
- private final static String RUNTIME_VIEW_CLASS_NAME = "org.xwalk.runtime.XWalkRuntimeView";
- private boolean mRuntimeLoaded = false;
- private Object mInstance;
- private Method mLoadAppFromUrl;
- private Method mLoadAppFromManifest;
- private Method mOnCreate;
- private Method mOnStart;
- private Method mOnResume;
- private Method mOnPause;
- private Method mOnStop;
- private Method mOnDestroy;
- private Method mOnActivityResult;
- private Method mOnNewIntent;
- private Method mEnableRemoteDebugging;
- private Method mDisableRemoteDebugging;
-
- // For instrumentation test.
- private Method mGetTitleForTest;
- private Method mSetCallbackForTest;
- private Method mLoadDataForTest;
-
- public XWalkRuntimeClient(Activity activity, AttributeSet attrs, CrossPackageWrapperExceptionHandler exceptionHandler) {
- super(activity, RUNTIME_VIEW_CLASS_NAME, exceptionHandler, Activity.class, Context.class, AttributeSet.class);
- Context libCtx = getLibraryContext();
- mInstance = this.createInstance(activity, libCtx, attrs);
- Method getVersion = lookupMethod("getVersion");
- String libVersion = (String) invokeMethod(getVersion, mInstance);
- if (libVersion == null) {
- // If the code executes to here and libVersion got is null, it means
- // the library package is available but native library is not.
- // It probably meets CPU arch mismatch, stop execution here to avoid crash.
- // A dialog should be prompt to user for this information.
- return;
- }
- if (!compareVersion(libVersion, getVersion())) {
- handleException(new XWalkRuntimeLibraryException(
- XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_NOT_UP_TO_DATE_CRITICAL));
- mInstance = null;
- return;
- }
- mRuntimeLoaded = true;
- mLoadAppFromUrl = lookupMethod("loadAppFromUrl", String.class);
- mLoadAppFromManifest = lookupMethod("loadAppFromManifest", String.class);
- mOnCreate = lookupMethod("onCreate");
- mOnStart = lookupMethod("onStart");
- mOnResume = lookupMethod("onResume");
- mOnPause = lookupMethod("onPause");
- mOnStop = lookupMethod("onStop");
- mOnDestroy = lookupMethod("onDestroy");
- mOnActivityResult = lookupMethod("onActivityResult", int.class, int.class, Intent.class);
- mOnNewIntent = lookupMethod("onNewIntent", Intent.class);
- mEnableRemoteDebugging = lookupMethod("enableRemoteDebugging", String.class, String.class);
- mDisableRemoteDebugging = lookupMethod("disableRemoteDebugging");
- }
-
- /**
- * Compare the given versions.
- * @param libVersion version of library apk
- * @param clientVersion version of client
- * @return true if library is not older than client, false otherwise or either of the version string
- * is invalid. Valid string should be \d+[\.\d+]*
- */
- private static boolean compareVersion(String libVersion, String clientVersion) {
- if (libVersion.equals(clientVersion)) {
- return true;
- }
- Pattern version = Pattern.compile("\\d+(\\.\\d+)*");
- Matcher lib = version.matcher(libVersion);
- Matcher client = version.matcher(clientVersion);
- if (lib.matches() && client.matches()) {
- StringTokenizer libTokens = new StringTokenizer(libVersion, ".");
- StringTokenizer clientTokens = new StringTokenizer(clientVersion, ".");
- int libTokenCount = libTokens.countTokens();
- int clientTokenCount = clientTokens.countTokens();
- if (libTokenCount == clientTokenCount) {
- while (libTokens.hasMoreTokens()) {
- int libValue = 0;
- int clientValue = 0;
- try {
- libValue = Integer.parseInt(libTokens.nextToken());
- clientValue = Integer.parseInt(clientTokens.nextToken());
- } catch (NumberFormatException e) {
- return false;
- }
- if (libValue == clientValue) continue;
- return libValue > clientValue;
- }
- return true;
- } else {
- return libTokenCount > clientTokenCount;
- }
- }
- return false;
- }
-
- @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;
- if (mRuntimeLoaded) {
- toHandle = new XWalkRuntimeLibraryException(
- XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_INVOKE_FAILED, e);
- } else {
- if (!(e instanceof XWalkRuntimeLibraryException)) {
- toHandle = new XWalkRuntimeLibraryException(
- XWalkRuntimeLibraryException.XWALK_RUNTIME_LIBRARY_NOT_INSTALLED, e);
- }
- }
- super.handleException(toHandle);
- }
-
- public FrameLayout get() {
- return (FrameLayout) mInstance;
- }
-
- /**
- * Get the version information of current runtime client.
- *
- * @return the string containing the version information.
- */
- public static String getVersion() {
- return XWalkRuntimeClientVersion.XWALK_RUNTIME_CLIENT_VERSION;
- }
-
- /**
- * Load a web application through the entry url. It may be
- * a file from assets or a url from network.
- *
- * @param url the url of loaded html resource.
- */
- public void loadAppFromUrl(String url) {
- invokeMethod(mLoadAppFromUrl, mInstance, url);
- }
-
- /**
- * Load a web application through the url of the manifest file.
- * The manifest file typically is placed in android assets. Now it is
- * compliant to W3C SysApps spec.
- *
- * @param manifestUrl the url of the manifest file
- */
- public void loadAppFromManifest(String manifestUrl) {
- invokeMethod(mLoadAppFromManifest, mInstance, manifestUrl);
- }
-
- /**
- * Tell runtime that the application is on creating. This can make runtime
- * be aware of application life cycle.
- */
- public void onCreate() {
- invokeMethod(mOnCreate, mInstance);
- }
-
- /**
- * Tell runtime that the application is on starting. This can make runtime
- * be aware of application life cycle.
- */
- public void onStart() {
- invokeMethod(mOnStart, mInstance);
- }
-
- /**
- * Tell runtime that the application is on resuming. This can make runtime
- * be aware of application life cycle.
- */
- public void onResume() {
- invokeMethod(mOnResume, mInstance);
- }
-
- /**
- * Tell runtime that the application is on pausing. This can make runtime
- * be aware of application life cycle.
- */
- public void onPause() {
- invokeMethod(mOnPause, mInstance);
- }
-
- /**
- * Tell runtime that the application is on stopping. This can make runtime
- * be aware of application life cycle.
- */
- public void onStop() {
- invokeMethod(mOnStop, mInstance);
- }
-
- /**
- * Tell runtime that the application is on destroying. This can make runtime
- * be aware of application life cycle.
- */
- public void onDestroy() {
- invokeMethod(mOnDestroy, mInstance);
- }
-
- /**
- * Tell runtime that one activity exists so that it can know the result code
- * of the exit code.
- *
- * @param requestCode the request code to identify where the result is from
- * @param resultCode the result code of the activity
- * @param data the data to contain the result data
- */
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- invokeMethod(mOnActivityResult, mInstance, requestCode, resultCode, data);
- }
-
- /**
- * Tell runtime that the activity receive a new Intent. The Intent may contain
- * data that runtime wants to deal with.
- * @param intent the new coming Intent.
- * @return boolean whether runtime consumed it.
- */
- public boolean onNewIntent(Intent intent) {
- Boolean handled = (Boolean) invokeMethod(mOnNewIntent, mInstance, intent);
- if (handled != null) return handled;
- return false;
- }
-
- /**
- * Enable remote debugging for the loaded web application. The caller
- * can set the url of debugging url. Besides, the socket name for remote
- * debugging has to be unique so typically the string can be appended
- * with the package name of the application.
- *
- * @param frontEndUrl the url of debugging url. If it's empty, then a
- * default url will be used.
- * @param socketName the unique socket name for setting up socket for
- * remote debugging.
- * @return the url of web socket for remote debugging.
- */
- public void enableRemoteDebugging(String frontEndUrl, String socketName) {
- invokeMethod(mEnableRemoteDebugging, mInstance, frontEndUrl, socketName);
- }
-
- /**
- * Disable remote debugging so runtime can close related stuff for
- * this feature.
- */
- public void disableRemoteDebugging() {
- invokeMethod(mDisableRemoteDebugging, mInstance);
- }
-
- // The following functions just for instrumentation test.
- public View getViewForTest() {
- return (View)mInstance;
- }
-
- public String getTitleForTest() {
- if (mGetTitleForTest == null) {
- mGetTitleForTest = lookupMethod("getTitleForTest");
- }
-
- return (String) invokeMethod(mGetTitleForTest, mInstance);
- }
-
- public void setCallbackForTest(Object callback) {
- if (mSetCallbackForTest == null) {
- mSetCallbackForTest = lookupMethod("setCallbackForTest", Object.class);
- }
-
- invokeMethod(mSetCallbackForTest, mInstance, callback);
- }
-
- public void loadDataForTest(String data, String mimeType, boolean isBase64Encoded) {
- if (mLoadDataForTest == null) {
- mLoadDataForTest = lookupMethod("loadDataForTest", String.class, String.class, boolean.class);
- }
-
- invokeMethod(mLoadDataForTest, mInstance, data, mimeType, isBase64Encoded);
- }
-}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.runtime;
+package org.xwalk.app.runtime;
import android.content.Context;
import android.graphics.Bitmap;
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.runtime;
+package org.xwalk.app.runtime;
import android.app.Activity;
import android.content.Context;
* @param context a context when creating this package
* @param attrs the attributes of the XML tag that is inflating the view
*/
- public XWalkRuntimeView(Activity activity, Context libContext, AttributeSet attrs) {
- super(libContext, attrs);
+ public XWalkRuntimeView(Activity activity, Context context, AttributeSet attrs) {
+ super(context, attrs);
// MixedContext is needed for cross package because the application
// context is different.
- init(new MixedContext(libContext, activity), activity);
+ init(context, activity);
}
/**
}
/**
- * Tell runtime that the application is on starting. This can make runtime
- * be aware of application life cycle.
- */
- public void onStart() {
- mProvider.onStart();
- }
-
- /**
* Tell runtime that the application is on resuming. This can make runtime
* be aware of application life cycle.
*/
}
/**
- * Tell runtime that the application is on stoping. This can make runtime
- * be aware of application life cycle.
- */
- public void onStop() {
- mProvider.onStop();
- }
-
- /**
* Tell runtime that the application is on destroying. This can make runtime
* be aware of application life cycle.
*/
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.runtime;
+package org.xwalk.app.runtime;
import android.app.Activity;
import android.content.Context;
interface XWalkRuntimeViewProvider {
// For handling life cycle and activity result.
public void onCreate();
- public void onStart();
public void onResume();
public void onPause();
- public void onStop();
public void onDestroy();
public void onActivityResult(int requestCode, int resultCode, Intent data);
public boolean onNewIntent(Intent intent);
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.runtime;
+package org.xwalk.app.runtime;
import android.app.Activity;
import android.content.Context;
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.core.internal.extension;
+package org.xwalk.app.runtime.extension;
import android.content.Context;
import android.content.Intent;
-import org.chromium.base.CalledByNative;
-
-import org.xwalk.core.internal.extensions.XWalkExtensionAndroid;
-import org.xwalk.core.internal.extension.XWalkExtension;
+import org.xwalk.core.XWalkExtension;
/**
* The extension bridge for the implementation based on xwalk core.
*/
-class XWalkCoreExtensionBridge extends XWalkExtensionAndroid implements XWalkExtensionBridge {
- private XWalkExtension mExtension;
+class XWalkCoreExtensionBridge extends XWalkExtension implements XWalkRuntimeExtensionBridge {
+ private XWalkExtensionClient mExtension;
- public XWalkCoreExtensionBridge(XWalkExtension extension) {
- super(extension.getExtensionName(), extension.getJsApi(), extension.getEntryPoints());
+ public XWalkCoreExtensionBridge(XWalkExtensionClient extension) {
+ super(extension.getExtensionName(), extension.getJsApi(), null);
mExtension = extension;
}
public void onDestroy() {
mExtension.onDestroy();
- destroyExtension();
}
public void onResume() {
package org.xwalk.app.runtime.extension;
-import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
-import java.lang.reflect.Method;
-import java.util.StringTokenizer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.xwalk.app.runtime.CrossPackageWrapper;
-
/**
* This class is to encapsulate the reflection detail of
* invoking XWalkExtension class in the shared library APK.
* below methods. It's created and registered by runtime side via the
* configuration information in extensions-config.json.
*/
-public class XWalkExtensionClient extends CrossPackageWrapper {
+public class XWalkExtensionClient {
+ // The unique name for this extension.
+ protected String mName;
- private final static String EXTENSION_CLASS_NAME = "org.xwalk.core.internal.extension.XWalkExtensionClientImpl";
- private Object mInstance;
- private Method mGetExtensionName;
- private Method mGetJsApi;
- private Method mPostMessage;
- private Method mBroadcastMessage;
+ // The JavaScript code stub. Will be injected to JS engine.
+ protected String mJsApi;
- protected XWalkExtensionContextClient mContext;
+ // The context used by extensions.
+ protected XWalkExtensionContextClient mExtensionContext;
+ /**
+ * Constructor with the information of an extension.
+ * @param name the extension name.
+ * @param apiVersion the version of API.
+ * @param jsApi the code stub of JavaScript for this extension.
+ * @param context the extension context.
+ */
public XWalkExtensionClient(String name, String jsApi, XWalkExtensionContextClient context) {
- super(context.getActivity(), EXTENSION_CLASS_NAME, null /* ExceptionHalder */, String.class, String.class,
- context.getInstance().getClass(), Object.class);
- mContext = context;
- mInstance = this.createInstance(name, jsApi, context.getInstance(), this);
-
- mGetExtensionName = lookupMethod("getExtensionName");
- mGetJsApi = lookupMethod("getJsApi");
- mPostMessage = lookupMethod("postMessage", int.class, String.class);
- mBroadcastMessage = lookupMethod("broadcastMessage", String.class);
+ assert (context != null);
+ mName = name;
+ mJsApi = jsApi;
+ mExtensionContext = context;
+ mExtensionContext.registerExtension(this);
}
/**
- * Get the extension name which is set when it's created.
+ * Get the unique name of extension.
+ * @return the name of extension set from constructor.
*/
public final String getExtensionName() {
- return (String)invokeMethod(mGetExtensionName, mInstance);
+ return mName;
}
/**
- * Get the JavaScript stub code which is set when it's created.
+ * Get the JavaScript code stub.
+ * @return the JavaScript code stub.
*/
public final String getJsApi() {
- return (String)invokeMethod(mGetJsApi, mInstance);
+ return mJsApi;
}
/**
return "";
}
+
/**
* Post messages to JavaScript via extension's context.
* It's used by child classes to post message from Java side
* to JavaScript side.
- * @param extensionInstanceID the ID of extension instance where the message came from.
+ * @param instanceID the ID of target extension instance.
* @param message the message to be passed to Javascript.
*/
- public final void postMessage(int extensionInstanceID, String message) {
- invokeMethod(mPostMessage, mInstance, extensionInstanceID, message);
+ public final void postMessage(int instanceID, String message) {
+ mExtensionContext.postMessage(this, instanceID, message);
}
/**
* @param message the message to be passed to Javascript.
*/
public final void broadcastMessage(String message) {
- invokeMethod(mBroadcastMessage, mInstance, message);
+ mExtensionContext.broadcastMessage(this, message);
}
}
import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-import java.lang.reflect.Method;
-import java.util.StringTokenizer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.xwalk.app.runtime.CrossPackageWrapper;
/**
- * This is the extension context used by external extensions. It'll be created
- * by runtime side.
+ * Interface for extension context
+ *
+ * It is responsible for maintaining all xwalk extensions and providing a way to
+ * post message to JavaScript side for each xwalk extension.
*/
-public final class XWalkExtensionContextClient extends CrossPackageWrapper {
- private final static String EXTENSION_CLASS_NAME =
- "org.xwalk.core.internal.extension.XWalkExtensionContextWrapper";
- private Object mInstance;
- private Method mGetContext;
- private Method mGetActivity;
+public interface XWalkExtensionContextClient {
+ /**
+ * Register an xwalk extension into context.
+ */
+ public void registerExtension(XWalkExtensionClient extension);
/**
- * It's called by runtime side.
+ * Unregister an xwalk extension with the given unique name from context.
*/
- public XWalkExtensionContextClient(Activity activity, Object instance) {
- super(activity, EXTENSION_CLASS_NAME, null, String.class, String.class,
- instance.getClass());
+ public void unregisterExtension(String name);
- mInstance = instance;
- mGetActivity = lookupMethod("getActivity");
- mGetContext = lookupMethod("getContext");
- }
+ /**
+ * Post a message to the given extension instance.
+ *
+ * @param extension The xwalk extension
+ * @param instanceId The unique id to identify the extension instance as the
+ * message destination.
+ * @param message The message content to be posted.
+ */
+ public void postMessage(XWalkExtensionClient extension, int instanceId, String message);
/**
- * Get the current Android Activity. Used by XWalkExtensionClient.
- * @return the current Android Activity.
+ * Broadcast a message to all extension instances.
+ *
+ * @param extension The xwalk extension
+ * @param message The message content to be broadcasted.
*/
- public Activity getActivity() {
- return (Activity) invokeMethod(mGetActivity, mInstance);
- }
+ public void broadcastMessage(XWalkExtensionClient extension, String message);
/**
- * Get the current Android Context. Used by XWalkExtensionClient.
+ * Get current Android Context.
* @return the current Android Context.
*/
- public Context getContext() {
- return (Context) invokeMethod(mGetContext, mInstance);
- }
+ public Context getContext();
/**
- * Get the object of the runtime side.
- * @return the object of the runtime side.
+ * Get the current Android Activity.
+ * @return the current Android Activity.
*/
- public Object getInstance() {
- return mInstance;
- }
+ public Activity getActivity();
}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.core.internal.extension;
+package org.xwalk.app.runtime.extension;
import android.content.Intent;
/**
* Interface for bridging XWalkExtension functionalities to its backend implementation.
*/
-interface XWalkExtensionBridge {
+interface XWalkRuntimeExtensionBridge {
/**
* Post a message from native to a specific receiver on JavaScript side.
*
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.core.internal.extension;
+package org.xwalk.app.runtime.extension;
/**
* A factory used to create the extension bridge.
*/
-final class XWalkExtensionBridgeFactory {
+final class XWalkRuntimeExtensionBridgeFactory {
/**
* Return a XWalkExtensionBridge instance for the given extension.
*/
- public static XWalkExtensionBridge createInstance(XWalkExtension extension) {
+ public static XWalkRuntimeExtensionBridge createInstance(XWalkExtensionClient extension) {
return new XWalkCoreExtensionBridge(extension);
}
}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.core.internal.extension;
+package org.xwalk.app.runtime.extension;
import android.app.Activity;
import android.content.Context;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import org.xwalk.core.internal.extension.api.contacts.Contacts;
-import org.xwalk.core.internal.extension.api.device_capabilities.DeviceCapabilities;
-import org.xwalk.core.internal.extension.api.launchscreen.LaunchScreenExtension;
-import org.xwalk.core.internal.extension.api.messaging.Messaging;
-import org.xwalk.core.internal.extension.api.presentation.PresentationExtension;
/**
* This internal class acts a manager to manage extensions.
*/
-public class XWalkExtensionManager implements XWalkExtensionContext {
+public class XWalkRuntimeExtensionManager implements XWalkExtensionContextClient {
private final static String TAG = "XWalkExtensionManager";
private final static String EXTENSION_CONFIG_FILE = "extensions-config.json";
- // This class name is from runtime client. Need to keep consistency with it.
- private final static String EXTENSION_CONTEXT_CLIENT_CLASS_NAME =
- "org.xwalk.app.runtime.extension.XWalkExtensionContextClient";
private final Context mContext;
private final Activity mActivity;
- private final HashMap<String, XWalkExtensionBridge> mExtensions = new HashMap<String, XWalkExtensionBridge>();
+ private final HashMap<String, XWalkRuntimeExtensionBridge> mExtensions = new HashMap<String, XWalkRuntimeExtensionBridge>();
// This variable is to set whether to load external extensions. The default is true.
private boolean mLoadExternalExtensions;
- public XWalkExtensionManager(Context context, Activity activity) {
+ public XWalkRuntimeExtensionManager(Context context, Activity activity) {
mContext = context;
mActivity = activity;
mLoadExternalExtensions = true;
}
@Override
- public void registerExtension(XWalkExtension extension) {
+ public void registerExtension(XWalkExtensionClient extension) {
if (mExtensions.get(extension.getExtensionName()) != null) {
Log.e(TAG, extension.getExtensionName() + "is already registered!");
return;
}
- XWalkExtensionBridge bridge = XWalkExtensionBridgeFactory.createInstance(extension);
+ XWalkRuntimeExtensionBridge bridge = XWalkRuntimeExtensionBridgeFactory.createInstance(extension);
mExtensions.put(extension.getExtensionName(), bridge);
}
@Override
public void unregisterExtension(String name) {
- XWalkExtensionBridge bridge = mExtensions.get(name);
+ XWalkRuntimeExtensionBridge bridge = mExtensions.get(name);
if (bridge != null) {
mExtensions.remove(name);
bridge.onDestroy();
}
@Override
- public void postMessage(XWalkExtension extension, int instanceID, String message) {
- XWalkExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
+ public void postMessage(XWalkExtensionClient extension, int instanceID, String message) {
+ XWalkRuntimeExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
if (bridge != null) bridge.postMessage(instanceID, message);
}
- public void broadcastMessage(XWalkExtension extension, String message) {
- XWalkExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
+ public void broadcastMessage(XWalkExtensionClient extension, String message) {
+ XWalkRuntimeExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
if (bridge != null) bridge.broadcastMessage(message);
}
public void onStart() {
- for(XWalkExtensionBridge extension: mExtensions.values()) {
+ for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
extension.onStart();
}
}
public void onResume() {
- for(XWalkExtensionBridge extension: mExtensions.values()) {
+ for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
extension.onResume();
}
}
public void onPause() {
- for(XWalkExtensionBridge extension: mExtensions.values()) {
+ for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
extension.onPause();
}
}
public void onStop() {
- for(XWalkExtensionBridge extension: mExtensions.values()) {
+ for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
extension.onStop();
}
}
public void onDestroy() {
- for(XWalkExtensionBridge extension: mExtensions.values()) {
+ for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
extension.onDestroy();
}
mExtensions.clear();
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- for(XWalkExtensionBridge extension: mExtensions.values()) {
+ for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
extension.onActivityResult(requestCode, resultCode, data);
}
}
public void loadExtensions() {
- loadInternalExtensions();
loadExternalExtensions();
}
mLoadExternalExtensions = load;
}
- private void loadInternalExtensions() {
- // Create all extension instances directly here. The internal extension will register
- // itself and add itself to XWalkExtensionManager.mExtensions automatically.
- // The following sample shows how to create an extension that named Device:
- // String jsApiContent = "";
- // try {
- // jsApiContent = getExtensionJSFileContent(mContext, Device.JS_API_PATH, true);
- // new Device(jsApiContent, mExtensionContextImpl);
- // } catch(IOException e) {
- // Log.w(TAG, "Failed to read js API file of internal extension: Device");
- // }
- {
- String jsApiContent = "";
- try {
- jsApiContent = getExtensionJSFileContent(
- mContext, PresentationExtension.JS_API_PATH, true);
- new PresentationExtension(jsApiContent, this);
- } catch (IOException e) {
- Log.w(TAG, "Failed to read JS API file: " + PresentationExtension.JS_API_PATH);
- }
- }
-
- {
- String jsApiContent = "";
- try {
- jsApiContent = getExtensionJSFileContent(
- mContext, LaunchScreenExtension.JS_API_PATH, true);
- new LaunchScreenExtension(jsApiContent, this);
- } catch (IOException e) {
- Log.w(TAG, "Failed to read JS API file: " + LaunchScreenExtension.JS_API_PATH);
- }
- }
-
- {
- String jsApiContent = "";
- try {
- jsApiContent = getExtensionJSFileContent(
- mContext, Contacts.JS_API_PATH, true);
- new Contacts(jsApiContent, this);
- } catch(IOException e) {
- Log.w(TAG, "Failed to read JS API file: " + Contacts.JS_API_PATH);
- }
- }
-
- {
- String jsApiContent = "";
- try {
- jsApiContent = getExtensionJSFileContent(
- mContext, DeviceCapabilities.JS_API_PATH, true);
- new DeviceCapabilities(jsApiContent, this);
- } catch(IOException e) {
- Log.w(TAG, "Failed to read JS API file: " + DeviceCapabilities.JS_API_PATH);
- }
- }
-
- {
- String jsApiContent = "";
- try {
- jsApiContent = getExtensionJSFileContent(
- mContext, Messaging.JS_API_PATH, true);
- new Messaging(jsApiContent, this);
- } catch(IOException e) {
- Log.w(TAG, "Failed to read JS API file: " + Messaging.JS_API_PATH);
- }
- }
- }
-
private void loadExternalExtensions() {
if (!mLoadExternalExtensions) return;
return;
}
- // Initialize the context for external extensions.
- XWalkExtensionContextWrapper contextWrapper =
- new XWalkExtensionContextWrapper(this);
- Object contextClient = createExtensionContextClient(contextWrapper);
-
try {
JSONArray jsonFeatures = new JSONArray(configFileContent);
int extensionCount = jsonFeatures.length();
}
if (name != null && className != null && jsApi != null) {
- createExternalExtension(name, className, jsApi, contextClient, contextWrapper);
+ createExternalExtension(name, className, jsApi, this);
}
}
} catch (JSONException e) {
return result;
}
- private Object createExtensionContextClient(XWalkExtensionContextWrapper contextWrapper) {
- Activity activity = contextWrapper.getActivity();
- try {
- Class<?> clazz = activity.getClassLoader().loadClass(EXTENSION_CONTEXT_CLIENT_CLASS_NAME);
- Constructor<?> constructor = clazz.getConstructor(Activity.class, Object.class);
- return constructor.newInstance(activity, contextWrapper);
- } catch (ClassNotFoundException e) {
- handleException(e);
- } catch (IllegalAccessException e) {
- handleException(e);
- } catch (InstantiationException e) {
- handleException(e);
- } catch (InvocationTargetException e) {
- handleException(e);
- } catch (NoSuchMethodException e) {
- handleException(e);
- }
- return null;
- }
-
private void createExternalExtension(String name, String className, String jsApi,
- Object contextClient, XWalkExtensionContextWrapper contextWrapper) {
- Activity activity = contextWrapper.getActivity();
+ XWalkExtensionContextClient extensionContext) {
+ Activity activity = extensionContext.getActivity();
try {
Class<?> clazz = activity.getClassLoader().loadClass(className);
Constructor<?> constructor = clazz.getConstructor(String.class,
- String.class, contextClient.getClass());
- constructor.newInstance(name, jsApi, contextClient);
+ String.class, XWalkExtensionContextClient.class);
+ constructor.newInstance(name, jsApi, this);
} catch (ClassNotFoundException e) {
handleException(e);
} catch (IllegalAccessException e) {
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.xwalk.runtime.client.embedded.shell">
- <application android:name="android.app.Application"
+ <application android:name="org.xwalk.core.XWalkApplication"
android:label="XWalkRuntimeClientEmbeddedShell" android:hardwareAccelerated="true">
<activity android:name="org.xwalk.runtime.client.embedded.shell.XWalkRuntimeClientEmbeddedShellActivity"
android:theme="@android:style/Theme.Holo.Light.NoActionBar"
@Override
protected void didTryLoadRuntimeView(View runtimeView) {
- if (getRuntimeView().get() != null) {
+ if (runtimeView != null) {
setContentView(R.layout.testshell_activity);
LinearLayout container = (LinearLayout) findViewById(R.id.content_container);
- container.addView(getRuntimeView().get(),
+ container.addView(runtimeView,
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
initializeUrlField();
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.xwalk.runtime.client.shell">
- <application android:name="org.xwalk.app.runtime.XWalkRuntimeApplication"
+ <application android:name="org.xwalk.core.XWalkApplication"
android:label="XWalkRuntimeClientShell" android:hardwareAccelerated="true">
<activity android:name="org.xwalk.runtime.client.shell.XWalkRuntimeClientShellActivity"
android:theme="@android:style/Theme.Holo.Light.NoActionBar"
@Override
protected void didTryLoadRuntimeView(View runtimeView) {
- if (getRuntimeView().get() != null) {
+ if (runtimeView != null) {
setContentView(R.layout.testshell_activity);
LinearLayout container = (LinearLayout) findViewById(R.id.content_container);
- container.addView(getRuntimeView().get(),
+ container.addView(runtimeView,
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
initializeUrlField();
import stat
import sys
+# get xwalk absolute path so we can run this script from any location
+xwalk_dir = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(xwalk_dir)
+
from app_info import AppInfo
from customize_launch_screen import CustomizeLaunchScreen
from handle_xml import AddElementAttribute
from handle_permissions import HandlePermissions
from xml.dom import minidom
+TEMPLATE_DIR_NAME = 'template'
def VerifyPackageName(value):
regex = r'^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$'
def Prepare(app_info, compressor):
- name = app_info.android_name
- package = app_info.package
+ """Copy the Android template project to a new app project
+ named app_info.app_name
+ """
+ # create new app_dir in xwalk_dir
+ app_name = app_info.android_name
+ app_dir = os.path.join(xwalk_dir, app_name)
+ app_package = app_info.package
app_root = app_info.app_root
- if os.path.exists(name):
- shutil.rmtree(name)
- shutil.copytree('template', name)
- shutil.rmtree(os.path.join(name, 'src'))
- src_root = os.path.join('template', 'src', 'org', 'xwalk', 'app', 'template')
- src_activity = os.path.join(src_root, 'AppTemplateActivity.java')
- if not os.path.isfile(src_activity):
- print ('Please make sure that the java file'
- ' of activity does exist.')
+ template_app_dir = os.path.join(xwalk_dir, TEMPLATE_DIR_NAME)
+
+ # 1) copy template project to app_dir
+ if os.path.exists(app_dir):
+ shutil.rmtree(app_dir)
+ shutil.copytree(template_app_dir, app_dir)
+
+ # 2) replace app_dir 'src' dir with template 'src' dir
+ shutil.rmtree(os.path.join(app_dir, 'src'))
+ template_src_root = os.path.join(template_app_dir, 'src', 'org', 'xwalk',
+ 'app', 'template')
+
+ # 3) Create directory tree from app package (org.xyz.foo -> src/org/xyz/foo)
+ # and copy AppTemplateActivity.java to <app_name>Activity.java
+ template_activity_file = os.path.join(template_src_root,
+ 'AppTemplateActivity.java')
+ if not os.path.isfile(template_activity_file):
+ print ('Error: The template file %s was not found. '
+ 'Please make sure this file exists.' % template_activity_file)
sys.exit(7)
- root_path = os.path.join(name, 'src', package.replace('.', os.path.sep))
- if not os.path.exists(root_path):
- os.makedirs(root_path)
- dest_activity = name + 'Activity.java'
- shutil.copyfile(src_activity, os.path.join(root_path, dest_activity))
+ app_pkg_dir = os.path.join(app_dir, 'src',
+ app_package.replace('.', os.path.sep))
+ if not os.path.exists(app_pkg_dir):
+ os.makedirs(app_pkg_dir)
+ app_activity_file = app_name + 'Activity.java'
+ shutil.copyfile(template_activity_file,
+ os.path.join(app_pkg_dir, app_activity_file))
+
+ # 4) Copy all HTML source from app_root to app_dir
if app_root:
- assets_path = os.path.join(name, 'assets', 'www')
- if os.path.isdir(assets_path):
- shutil.rmtree(assets_path)
- shutil.copytree(app_root, assets_path)
+ app_assets_dir = os.path.join(app_dir, 'assets', 'www')
+ if os.path.isdir(app_assets_dir):
+ shutil.rmtree(app_assets_dir)
+ shutil.copytree(app_root, app_assets_dir)
if compressor:
- CompressSourceFiles(assets_path, compressor)
+ CompressSourceFiles(app_assets_dir, compressor)
def EncodingUnicodeValue(value):
def CustomizeStringXML(name, description):
- strings_path = os.path.join(name, 'res', 'values', 'strings.xml')
+ strings_path = os.path.join(xwalk_dir, name, 'res', 'values', 'strings.xml')
if not os.path.isfile(strings_path):
print ('Please make sure strings_xml'
' exists under template folder.')
def CustomizeThemeXML(name, fullscreen, manifest):
- theme_path = os.path.join(name, 'res', 'values-v14', 'theme.xml')
+ theme_path = os.path.join(xwalk_dir, name, 'res', 'values-v14', 'theme.xml')
if not os.path.isfile(theme_path):
print('Error: theme.xml is missing in the build tool.')
sys.exit(6)
# append a space before '@' or '?' to fix that.
if app_name.startswith('@') or app_name.startswith('?'):
app_name = ' ' + app_name
- manifest_path = os.path.join(name, 'AndroidManifest.xml')
+ manifest_path = os.path.join(xwalk_dir, name, 'AndroidManifest.xml')
if not os.path.isfile(manifest_path):
print ('Please make sure AndroidManifest.xml'
' exists under template folder.')
EditElementAttribute(xmldoc, 'application', 'android:icon',
'@drawable/%s' % icon_name)
- file_handle = open(os.path.join(name, 'AndroidManifest.xml'), 'w')
+ file_handle = open(os.path.join(xwalk_dir, name, 'AndroidManifest.xml'), 'w')
xmldoc.writexml(file_handle, encoding='utf-8')
file_handle.close()
def CustomizeJava(app_info, app_url, app_local_path, keep_screen_on):
name = app_info.android_name
package = app_info.package
- root_path = os.path.join(name, 'src', package.replace('.', os.path.sep))
- dest_activity = os.path.join(root_path, name + 'Activity.java')
+ app_pkg_dir = os.path.join(xwalk_dir, name, 'src',
+ package.replace('.', os.path.sep))
+ dest_activity = os.path.join(app_pkg_dir, name + 'Activity.java')
ReplaceString(dest_activity, 'org.xwalk.app.template', package)
ReplaceString(dest_activity, 'AppTemplate', name)
- manifest_file = os.path.join(name, 'assets/www', 'manifest.json')
+ manifest_file = os.path.join(xwalk_dir, name, 'assets/www', 'manifest.json')
if os.path.isfile(manifest_file):
ReplaceString(
dest_activity,
ReplaceString(dest_activity, 'file:///android_asset/www/index.html',
app_url)
elif app_local_path:
- if os.path.isfile(os.path.join(name, 'assets/www', app_local_path)):
+ if os.path.isfile(os.path.join(xwalk_dir, name, 'assets/www',
+ app_local_path)):
ReplaceString(dest_activity, 'file:///android_asset/www/index.html',
'app://' + package + '/' + app_local_path)
else:
if not extensions:
return
name = app_info.android_name
- apk_path = name
+ apk_path = os.path.join(xwalk_dir, name)
apk_assets_path = os.path.join(apk_path, 'assets')
extensions_string = 'xwalk-extensions'
json_output['jsapi'] = js_path_prefix + json_output['jsapi']
extension_json_list.append(json_output)
# Merge the permissions of extensions into AndroidManifest.xml.
- manifest_path = os.path.join(name, 'AndroidManifest.xml')
+ manifest_path = os.path.join(xwalk_dir, name, 'AndroidManifest.xml')
xmldoc = minidom.parse(manifest_path)
if ('permissions' in json_output):
# Get used permission list to avoid repetition as "--permissions"
def GenerateCommandLineFile(app_info, xwalk_command_line):
if xwalk_command_line == '':
return
- assets_path = os.path.join(app_info.android_name, 'assets')
+ assets_path = os.path.join(xwalk_dir, app_info.android_name, 'assets')
file_path = os.path.join(assets_path, 'xwalk-command-line')
command_line_file = open(file_path, 'w')
command_line_file.write('xwalk ' + xwalk_command_line)
for kd, vd in drawable_dict.items():
for item in icon_list:
if item[0] >= vd[0] and item[0] < vd[1]:
- drawable_path = os.path.join(name, 'res', 'drawable-' + kd)
+ drawable_path = os.path.join(xwalk_dir, name, 'res', 'drawable-' + kd)
if not os.path.exists(drawable_path):
os.makedirs(drawable_path)
icon = os.path.join(app_root, item[1])
def CustomizeIconByOption(name, icon):
if os.path.isfile(icon):
- drawable_path = os.path.join(name, 'res', 'drawable')
+ drawable_path = os.path.join(xwalk_dir, name, 'res', 'drawable')
if not os.path.exists(drawable_path):
os.makedirs(drawable_path)
icon_file = os.path.basename(icon)
if options.name is not None:
app_info.android_name = options.name
if options.app_root is None:
- app_info.app_root = os.path.join('test_data', 'manifest')
+ app_info.app_root = os.path.join(xwalk_dir, 'test_data', 'manifest')
else:
app_info.app_root = options.app_root
if options.package is not None:
import shutil
import sys
+xwalk_dir = os.path.dirname(os.path.abspath(__file__))
def CopyToPathWithName(root, name, final_path, rename):
if name == '':
def CopyDrawables(image_dict, orientation, sanitized_name, name, app_root):
- drawable = os.path.join(sanitized_name, 'res', 'drawable')
+ drawable = os.path.join(xwalk_dir, sanitized_name, 'res', 'drawable')
if orientation == 'landscape':
drawable = drawable + '-land'
elif orientation == 'portrait':
orientation,
sanitized_name,
app_root):
- background_path = os.path.join(sanitized_name, 'res',
+ background_path = os.path.join(xwalk_dir, 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.')
--- /dev/null
+#!/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.
+# pylint: disable=F0401
+
+import fnmatch
+import json
+import optparse
+import os
+import sys
+
+from util import CleanDir, RunCommand, GetVersion
+
+
+"""
+* Fodler structure for extension.
+1. 1 extension of 1 repo.
+.
+|-- all.gyp #optional. If your extension is built from source.
+| You have to provide this file.
+|-- build.json #required. Tell make_apk.json where to find extension.
+|-- <other files and dirs>
+
+2. multiple extesnions of 1 repo
+.
+|-- all.gyp
+|-- <extension>
+ |-- build.json
+ |-- <other files and dirs>
+
+* Format of build.json
+Example:
+{
+ "binary_path":"../out/Default/gen/iap"
+}
+The base dir of "binary_path" is the path of extension.
+"""
+
+
+def GetExtensionList(extensions_path):
+ if not os.path.isdir(extensions_path):
+ return []
+
+ extension_list = []
+ for item in os.listdir(extensions_path):
+ sub_path = os.path.join(extensions_path, item)
+ if not os.path.isdir(sub_path):
+ continue
+ if os.path.isfile(os.path.join(sub_path, "build.json")):
+ extension_list.append(item)
+ else:
+ for sub_item in os.listdir(sub_path):
+ if os.path.isfile(
+ os.path.join(sub_path, sub_item, "build.json")):
+ extension_list.append(os.path.join(item, sub_item))
+
+ return extension_list
+
+
+def EnableExtension(extension_name, extensions_path, is_enable):
+ extension_list = GetExtensionList(extensions_path)
+ filtered_extensions = fnmatch.filter(extension_list, extension_name)
+ for item in filtered_extensions:
+ build_json_path = os.path.join(extensions_path, item, "build.json")
+ with open(build_json_path, "r") as fd:
+ data = json.load(fd)
+ data["enable"] = is_enable
+ with open(build_json_path, "w") as fd:
+ fd.write(
+ json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')))
+
+
+def GetExtensionStatus(extension_name, extensions_path):
+ build_json_path = os.path.join(extensions_path, extension_name, "build.json")
+ with open(build_json_path, "r") as fd:
+ data = json.load(fd)
+ return data.get('enable', True)
+
+
+def BuildExtension(repo_path):
+ old_cwd = os.getcwd()
+ os.chdir(repo_path)
+ os.environ["GYP_GENERATORS"] = "ninja"
+ gyp_cmd = ["gyp", "--depth=.", "all.gyp"]
+ RunCommand(gyp_cmd, True)
+ #Currently, the output path is set to out/Default.
+ ninja_cmd = ["ninja", "-C", os.path.join("out", "Default")]
+ RunCommand(ninja_cmd, True)
+ os.chdir(old_cwd)
+
+
+def HandleAdd(git_url, extensions_path, name=None):
+ if name is None:
+ name = git_url.split('/')[-1].split('.')[0]
+ if not os.path.isdir(extensions_path):
+ if os.path.isfile(extensions_path):
+ print "WARNING: Please remove file %s" % (extensions_path)
+ sys.exit(1)
+ else:
+ os.mkdir(extensions_path)
+ local_extension_path = os.path.join(extensions_path, name)
+ if os.path.exists(local_extension_path):
+ print "ERROR: You already have a repo named \"%s\"." % name
+ return
+ os.mkdir(local_extension_path)
+ #Only support git.
+ git_cmd = ["git", "clone", git_url, local_extension_path]
+ RunCommand(git_cmd, True)
+ if os.path.isfile(os.path.join(local_extension_path, "all.gyp")):
+ BuildExtension(local_extension_path)
+
+
+def HandleRemove(remove_name, extensions_path):
+ extension_path = os.path.join(extensions_path, remove_name)
+ if os.path.exists(extension_path):
+ CleanDir(extension_path)
+ else:
+ print "ERROR: Don't have extension \"%s\"" % (remove_name)
+
+
+def PrintExtensionInfo(extension_name, extensions_path):
+ print "{0} {1}".format(
+ "+" if GetExtensionStatus(extension_name, extensions_path) else "-",
+ extension_name)
+
+
+def HandleList(extensions_path):
+ extension_list = GetExtensionList(extensions_path)
+ print
+ for extension_name in extension_list:
+ PrintExtensionInfo(extension_name, extensions_path)
+ print
+
+
+def HandleSearch(key, extensions_path):
+ extension_list = GetExtensionList(extensions_path)
+ filtered_extensions = fnmatch.filter(extension_list, key)
+ print
+ for extension_name in filtered_extensions:
+ PrintExtensionInfo(extension_name, extensions_path)
+ print
+
+
+def HandleEnable(extension_name, extension_path):
+ EnableExtension(extension_name, extension_path, True)
+
+
+def HandleDisable(extension_name, extension_path):
+ EnableExtension(extension_name, extension_path, False)
+
+
+def HandleVersion():
+ version_path = \
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), "VERSION")
+ if os.path.isfile(version_path):
+ print(GetVersion("VERSION"))
+ else:
+ print ("ERROR: VERSION was not found, so Crosswalk\'s version could not"
+ "be determined.")
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ parser.add_option("--add", action="store",
+ type="string", dest="git_url",
+ metavar="URL",
+ help="Add an extension")
+ parser.add_option("--enable", action="store",
+ type="string", dest="enable",
+ metavar="NAME",
+ help="Enabled extension list")
+ parser.add_option("--disable", action="store",
+ type="string", dest="disable",
+ metavar="NAME",
+ help="Disabled extension list")
+ parser.add_option("--name", action="store",
+ type="string", dest="name",
+ metavar="NAME",
+ help="Extension name in local path. "
+ "Work with --add option.")
+ parser.add_option("--remove", action="store",
+ type="string", dest="remove_name",
+ metavar="NAME",
+ help="Remove an extension")
+ parser.add_option("-l", "--list", action="store_true",
+ dest="list_extensions", default=False,
+ help="List all extensions")
+ parser.add_option("--search", action="store",
+ type="string", dest="search_key",
+ metavar="KEYWORD",
+ help="List all extensions")
+ parser.add_option("-v", "--version", action="store_true",
+ dest="version", default=False,
+ help="The version of this python tool.")
+
+ options, _ = parser.parse_args()
+ if len(argv) == 1:
+ parser.print_help()
+ return 0
+
+ extensions_path = os.path.join(os.getcwd(), "extensions")
+
+ if options.git_url:
+ HandleAdd(options.git_url, extensions_path, options.name)
+ elif options.enable:
+ HandleEnable(options.enable, extensions_path)
+ elif options.disable:
+ HandleDisable(options.disable, extensions_path)
+ elif options.remove_name:
+ HandleRemove(options.remove_name, extensions_path)
+ elif options.list_extensions:
+ HandleList(extensions_path)
+ elif options.search_key:
+ HandleSearch(options.search_key, extensions_path)
+ elif options.version:
+ HandleVersion()
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
# found in the LICENSE file.
# pylint: disable=F0401
+import json
import optparse
import os
import re
import subprocess
import sys
+# get xwalk absolute path so we can run this script from any location
+xwalk_dir = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(xwalk_dir)
+
from app_info import AppInfo
from customize import VerifyPackageName, CustomizeAll, \
ParseParameterForCompressor
+from extension_manager import GetExtensionList, GetExtensionStatus
from handle_permissions import permission_mapping_table
+from util import AllArchitectures, CleanDir, GetVersion, RunCommand
from manifest_json_parser import HandlePermissionList
from manifest_json_parser import ManifestJsonParser
NATIVE_LIBRARY = 'libxwalkcore.so'
-def CleanDir(path):
- if os.path.exists(path):
- shutil.rmtree(path)
-
-
-def AllArchitectures():
- return ("x86", "arm")
-
-
def ConvertArchNameToArchFolder(arch):
arch_dict = {
'x86': 'x86',
return result
-def RunCommand(command, verbose=False, shell=False):
- """Runs the command list, print the output, and propagate its result."""
- proc = subprocess.Popen(command, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT, shell=shell)
- if not shell:
- output = proc.communicate()[0]
- result = proc.returncode
- if verbose:
- print(output.decode("utf-8").strip())
- if result != 0:
- print ('Command "%s" exited with non-zero exit code %d'
- % (' '.join(command), result))
- sys.exit(result)
- return output.decode("utf-8")
-
-
def Which(name):
"""Searches PATH for executable files with the given name, also taking
PATHEXT into account. Returns the first existing match, or None if no matches
return max(targets)
-def GetVersion(path):
- """Get the version of this python tool."""
- version_str = 'Crosswalk app packaging tool version is '
- file_handle = open(path, 'r')
- src_content = file_handle.read()
- version_nums = re.findall(r'\d+', src_content)
- version_str += ('.').join(version_nums)
- file_handle.close()
- return version_str
-
-
def ContainsNativeLibrary(path):
return os.path.isfile(os.path.join(path, NATIVE_LIBRARY))
def ParseXPK(options, out_dir):
- cmd = ['python', 'parse_xpk.py',
+ cmd = ['python', os.path.join (xwalk_dir, 'parse_xpk.py'),
'--file=%s' % os.path.expanduser(options.xpk),
'--out=%s' % out_dir]
RunCommand(cmd)
return '%s%s' % (abi, b.zfill(7))
+def GetExtensionBinaryPathList():
+ local_extension_list = []
+ extensions_path = os.path.join(os.getcwd(), "extensions")
+ exist_extension_list = GetExtensionList(extensions_path)
+ for item in exist_extension_list:
+ build_json_path = os.path.join(extensions_path, item, "build.json")
+ with open(build_json_path) as fd:
+ data = json.load(fd)
+ if not GetExtensionStatus(item, extensions_path):
+ continue
+ else:
+ if data.get("binary_path", False):
+ extension_binary_path = os.path.join(extensions_path,
+ item,
+ data["binary_path"])
+ else:
+ print "The extension \"%s\" doesn't exists." % item
+ sys.exit(1)
+ if os.path.isdir(extension_binary_path):
+ local_extension_list.append(extension_binary_path)
+ else:
+ print "The extension \"%s\" doesn't exists." % item
+ sys.exit(1)
+
+ return local_extension_list
+
+
def Customize(options, app_info, manifest):
app_info.package = options.package
app_info.app_name = options.name
app_info.orientation = options.orientation
if options.icon:
app_info.icon = '%s' % os.path.expanduser(options.icon)
+
+ #Add local extensions to extension list.
+ extension_binary_path_list = GetExtensionBinaryPathList()
+ if len(extension_binary_path_list) > 0:
+ if options.extensions is None:
+ options.extensions = ""
+ else:
+ options.extensions += os.pathsep
+
+ for item in extension_binary_path_list:
+ options.extensions += item
+ options.extensions += os.pathsep
+ #trim final path separator
+ options.extensions = options.extensions[0:-1]
+
CustomizeAll(app_info, options.description, options.icon_dict,
options.permissions, options.app_url, options.app_local_path,
options.keep_screen_on, options.extensions, manifest,
else:
print ('Use xwalk\'s keystore by default for debugging. '
'Please switch to your keystore when distributing it to app market.')
- key_store = 'xwalk-debug.keystore'
+ key_store = os.path.join(xwalk_dir, 'xwalk-debug.keystore')
key_alias = 'xwalkdebugkey'
key_code = 'xwalkdebug'
key_alias_code = 'xwalkdebug'
# Update android project for app and xwalk_core_library.
update_project_cmd = ['android', 'update', 'project',
- '--path', name, '--target', target_string,
+ '--path', os.path.join (xwalk_dir, name),
+ '--target', target_string,
'--name', name]
if options.mode == 'embedded':
RunCommand(['android', 'update', 'lib-project',
- '--path', os.path.join(name, 'xwalk_core_library'),
+ '--path', os.path.join(xwalk_dir, name, 'xwalk_core_library'),
'--target', target_string])
update_project_cmd.extend(['-l', 'xwalk_core_library'])
else:
# Shared mode doesn't need xwalk_runtime_java.jar.
- os.remove(os.path.join(name, 'libs', 'xwalk_runtime_java.jar'))
+ os.remove(os.path.join(xwalk_dir, name, 'libs', 'xwalk_runtime_java.jar'))
RunCommand(update_project_cmd)
# Check whether external extensions are included.
extensions_string = 'xwalk-extensions'
- extensions_dir = os.path.join(os.getcwd(), name, extensions_string)
+ extensions_dir = os.path.join(xwalk_dir, name, extensions_string)
external_extension_jars = FindExtensionJars(extensions_dir)
for external_extension_jar in external_extension_jars:
shutil.copyfile(external_extension_jar,
- os.path.join(name, 'libs',
+ os.path.join(xwalk_dir, name, 'libs',
os.path.basename(external_extension_jar)))
if options.mode == 'embedded':
if not arch:
print ('Invalid CPU arch: %s.' % arch)
sys.exit(10)
- library_lib_path = os.path.join(name, 'xwalk_core_library', 'libs')
+ library_lib_path = os.path.join(xwalk_dir, name, 'xwalk_core_library',
+ 'libs')
for dir_name in os.listdir(library_lib_path):
lib_dir = os.path.join(library_lib_path, dir_name)
if ContainsNativeLibrary(lib_dir):
shutil.rmtree(lib_dir)
- native_lib_path = os.path.join(name, 'native_libs', arch)
+ native_lib_path = os.path.join(xwalk_dir, name, 'native_libs', arch)
if ContainsNativeLibrary(native_lib_path):
shutil.copytree(native_lib_path, os.path.join(library_lib_path, arch))
else:
'embedded APK.' % arch)
sys.exit(10)
- ant_cmd = ['ant', 'release', '-f', os.path.join(name, 'build.xml')]
+ ant_cmd = ['ant', 'release', '-f', os.path.join(xwalk_dir, name, 'build.xml')]
if not options.verbose:
ant_cmd.extend(['-quiet'])
ant_cmd.extend(['-Dkey.store="%s"' % os.path.abspath(key_store)])
% (' '.join(ant_cmd), ant_result))
sys.exit(ant_result)
- src_file = os.path.join(name, 'bin', '%s-release.apk' % name)
+ src_file = os.path.join(xwalk_dir, name, 'bin', '%s-release.apk' % name)
package_name = name
if options.app_version:
package_name += ('_' + options.app_version)
# out.
# When making apk for specified CPU arch, will only include the
# corresponding native library by copying it back into xwalk_core_library.
- target_library_path = os.path.join(name, 'xwalk_core_library')
- shutil.copytree('xwalk_core_library', target_library_path)
+ target_library_path = os.path.join(xwalk_dir, name, 'xwalk_core_library')
+ shutil.copytree(os.path.join(xwalk_dir, 'xwalk_core_library'),
+ target_library_path)
library_lib_path = os.path.join(target_library_path, 'libs')
- native_lib_path = os.path.join(name, 'native_libs')
+ native_lib_path = os.path.join(xwalk_dir, name, 'native_libs')
os.makedirs(native_lib_path)
available_archs = []
for dir_name in os.listdir(library_lib_path):
xpk_temp_dir = ''
if options.xpk:
xpk_name = os.path.splitext(os.path.basename(options.xpk))[0]
- xpk_temp_dir = xpk_name + '_xpk'
+ xpk_temp_dir = os.path.join(xwalk_dir, xpk_name + '_xpk')
ParseXPK(options, xpk_temp_dir)
if options.app_root and not options.manifest:
--- /dev/null
+#!/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.
+# pylint: disable=F0401
+
+
+import os
+import re
+import shutil
+import subprocess
+import sys
+
+
+def CleanDir(path):
+ if os.path.exists(path):
+ shutil.rmtree(path)
+
+
+def AllArchitectures():
+ return ("x86", "arm")
+
+
+def RunCommand(command, verbose=False, shell=False):
+ """Runs the command list, print the output, and propagate its result."""
+ proc = subprocess.Popen(command, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, shell=shell)
+ if not shell:
+ output = proc.communicate()[0]
+ result = proc.returncode
+ if verbose:
+ print(output.decode("utf-8").strip())
+ if result != 0:
+ print ('Command "%s" exited with non-zero exit code %d'
+ % (' '.join(command), result))
+ sys.exit(result)
+ return output.decode("utf-8")
+ else:
+ return None
+
+
+def GetVersion(path):
+ """Get the version of this python tool."""
+ version_str = 'Crosswalk app packaging tool version is '
+ file_handle = open(path, 'r')
+ src_content = file_handle.read()
+ version_nums = re.findall(r'\d+', src_content)
+ version_str += ('.').join(version_nums)
+ file_handle.close()
+ return version_str
#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/runtime/browser/xwalk_runner.h"
+#if defined(OS_TIZEN)
+#include "xwalk/application/browser/application_tizen.h"
+#endif
+
using content::RenderProcessHost;
namespace xwalk {
namespace application {
+scoped_ptr<Application> Application::Create(
+ scoped_refptr<ApplicationData> data,
+ RuntimeContext* context) {
+#if defined(OS_TIZEN)
+ return make_scoped_ptr<Application>(new ApplicationTizen(data, context));
+#else
+ return make_scoped_ptr(new Application(data, context));
+#endif
+}
+
Application::Application(
scoped_refptr<ApplicationData> data,
- RuntimeContext* runtime_context,
- Observer* observer)
+ RuntimeContext* runtime_context)
: data_(data),
render_process_host_(NULL),
web_contents_(NULL),
security_mode_enabled_(false),
runtime_context_(runtime_context),
- observer_(observer),
- entry_point_used_(Default),
+ observer_(NULL),
remote_debugging_enabled_(false),
weak_factory_(this) {
DCHECK(runtime_context_);
- DCHECK(data_.get());
- DCHECK(observer_);
+ DCHECK(data_);
}
Application::~Application() {
render_process_host_->RemoveObserver(this);
}
-bool Application::Launch(const LaunchParams& launch_params) {
- if (!runtimes_.empty()) {
- LOG(ERROR) << "Attempt to launch app: " << id()
- << " that was already launched.";
- return false;
+template<>
+GURL Application::GetStartURL<Package::WGT>() {
+ GURL url = GetAbsoluteURLFromKey(widget_keys::kLaunchLocalPathKey);
+ if (!url.is_valid()) {
+ LOG(WARNING) << "Failed to find start URL from the 'config.xml'"
+ << "trying to find default entry page.";
+ url = GetDefaultWidgetEntryPage(data_);
}
- CHECK(!render_process_host_);
-
- GURL url = GetStartURL(launch_params, &entry_point_used_);
- if (!url.is_valid())
- return false;
-
- remote_debugging_enabled_ = launch_params.remote_debugging;
-
- Runtime* runtime = Runtime::Create(
- runtime_context_,
- this, content::SiteInstance::CreateForURL(runtime_context_, url));
- render_process_host_ = runtime->GetRenderProcessHost();
- render_process_host_->AddObserver(this);
- web_contents_ = runtime->web_contents();
- InitSecurityPolicy();
- runtime->LoadURL(url);
-
- NativeAppWindow::CreateParams params;
- params.net_wm_pid = launch_params.launcher_pid;
- if (data_->GetPackageType() == Package::WGT)
- params.state = GetWindowShowStateWGT(launch_params);
- else
- params.state = GetWindowShowStateXPK(launch_params);
-
- params.splash_screen_path = GetSplashScreenPath();
-
- runtime->AttachWindow(params);
-
- return true;
-}
-
-GURL Application::GetStartURL(const LaunchParams& params,
- LaunchEntryPoint* used) {
- if (params.entry_points & StartURLKey) {
- GURL url = GetAbsoluteURLFromKey(keys::kStartURLKey);
- if (url.is_valid()) {
- *used = StartURLKey;
- return url;
+ if (url.is_valid()) {
+#if defined(OS_TIZEN)
+ if (data_->IsHostedApp() && !url.SchemeIsHTTPOrHTTPS()) {
+ LOG(ERROR) << "Hosted apps are only supported with"
+ "http:// or https:// scheme.";
+ return GURL();
}
+#endif
+ return url;
}
- if (params.entry_points & LaunchLocalPathKey) {
- GURL url = GetAbsoluteURLFromKey(
- GetLaunchLocalPathKey(data_->GetPackageType()));
+ LOG(WARNING) << "Failed to find a valid start URL in the manifest.";
+ return GURL();
+}
- if (!url.is_valid() && data_->GetPackageType() == Package::WGT)
- url = GetDefaultWidgetEntryPage(data_);
+template<>
+GURL Application::GetStartURL<Package::XPK>() {
+ GURL url = GetAbsoluteURLFromKey(keys::kStartURLKey);
+ if (url.is_valid())
+ return url;
- if (url.is_valid()) {
-#if defined(OS_TIZEN)
- if (data_->IsHostedApp() && !url.SchemeIsHTTPOrHTTPS()) {
- LOG(ERROR) << "Hosted application should use the url start with"
- "http or https as its entry page.";
- return GURL();
- }
-#endif
- *used = LaunchLocalPathKey;
- return url;
- }
- }
+ url = GetAbsoluteURLFromKey(keys::kLaunchLocalPathKey);
+ if (url.is_valid())
+ return url;
- if (params.entry_points & URLKey) {
+ url = GetAbsoluteURLFromKey(keys::kDeprecatedURLKey);
+ if (url.is_valid()) {
LOG(WARNING) << "Deprecated key '" << keys::kDeprecatedURLKey
<< "' found. Please migrate to using '" << keys::kStartURLKey
<< "' instead.";
- GURL url = GetAbsoluteURLFromKey(keys::kDeprecatedURLKey);
- if (url.is_valid()) {
- *used = URLKey;
- return url;
- }
+ return url;
}
LOG(WARNING) << "Failed to find a valid start URL in the manifest.";
return GURL();
}
-ui::WindowShowState Application::GetWindowShowStateWGT(
+
+template<>
+ui::WindowShowState Application::GetWindowShowState<Package::WGT>(
const LaunchParams& params) {
if (params.force_fullscreen)
return ui::SHOW_STATE_FULLSCREEN;
return ui::SHOW_STATE_DEFAULT;
}
-ui::WindowShowState Application::GetWindowShowStateXPK(
+template<>
+ui::WindowShowState Application::GetWindowShowState<Package::XPK>(
const LaunchParams& params) {
if (params.force_fullscreen)
return ui::SHOW_STATE_FULLSCREEN;
return ui::SHOW_STATE_DEFAULT;
}
+bool Application::Launch(const LaunchParams& launch_params) {
+ if (!runtimes_.empty()) {
+ LOG(ERROR) << "Attempt to launch app with id " << id()
+ << ", but it is already running.";
+ return false;
+ }
+
+ CHECK(!render_process_host_);
+ bool is_wgt = data_->GetPackageType() == Package::WGT;
+
+ GURL url = is_wgt ? GetStartURL<Package::WGT>():
+ GetStartURL<Package::XPK>();
+ if (!url.is_valid())
+ return false;
+
+ remote_debugging_enabled_ = launch_params.remote_debugging;
+
+ Runtime* runtime = Runtime::Create(
+ runtime_context_,
+ this, content::SiteInstance::CreateForURL(runtime_context_, url));
+ render_process_host_ = runtime->GetRenderProcessHost();
+ render_process_host_->AddObserver(this);
+ web_contents_ = runtime->web_contents();
+ InitSecurityPolicy();
+ runtime->LoadURL(url);
+
+ NativeAppWindow::CreateParams params;
+ params.net_wm_pid = launch_params.launcher_pid;
+ params.state = is_wgt ? GetWindowShowState<Package::WGT>(launch_params):
+ GetWindowShowState<Package::XPK>(launch_params);
+
+ params.splash_screen_path = GetSplashScreenPath();
+
+ runtime->AttachWindow(params);
+
+ return true;
+}
+
GURL Application::GetAbsoluteURLFromKey(const std::string& key) {
const Manifest* manifest = data_->GetManifest();
std::string source;
if (!manifest->GetString(key, &source) || source.empty())
return GURL();
- std::size_t found = source.find_first_of("://");
+ std::size_t found = source.find("://");
if (found == std::string::npos)
return data_->GetResourceURL(source);
return GURL(source);
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&Application::NotifyTermination,
weak_factory_.GetWeakPtr()));
- return;
}
}
void Application::NotifyTermination() {
CHECK(!render_process_host_);
- observer_->OnApplicationTerminated(this);
+ if (observer_)
+ observer_->OnApplicationTerminated(this);
}
bool Application::UseExtension(const std::string& extension_name) const {
virtual ~Observer() {}
};
- // Manifest keys that can be used as application entry points.
- enum LaunchEntryPoint {
- StartURLKey = 1 << 0, // start_url
- LaunchLocalPathKey = 1 << 1, // app.launch.local_path
- URLKey = 1 << 2, // url
- Default = StartURLKey | LaunchLocalPathKey
- };
- typedef unsigned LaunchEntryPoints;
-
struct LaunchParams {
- LaunchParams() :
- entry_points(Default),
- launcher_pid(0),
- force_fullscreen(false),
- remote_debugging(false) {}
-
- LaunchEntryPoints entry_points;
-
// Used only when running as service. Specifies the PID of the launcher
// process.
int32 launcher_pid;
StoredPermission perm);
bool CanRequestURL(const GURL& url) const;
+ void set_observer(Observer* observer) { observer_ = observer; }
+
protected:
- // We enforce ApplicationService ownership.
- friend class ApplicationService;
- Application(scoped_refptr<ApplicationData> data,
- RuntimeContext* context,
- Observer* observer);
+ Application(scoped_refptr<ApplicationData> data, RuntimeContext* context);
virtual bool Launch(const LaunchParams& launch_params);
virtual void InitSecurityPolicy();
}
private:
+ // We enforce ApplicationService ownership.
+ friend class ApplicationService;
+ static scoped_ptr<Application> Create(scoped_refptr<ApplicationData> data,
+ RuntimeContext* context);
// Runtime::Observer implementation.
virtual void OnRuntimeAdded(Runtime* runtime) OVERRIDE;
virtual void OnRuntimeRemoved(Runtime* runtime) OVERRIDE;
// Try to extract the URL from different possible keys for entry points in the
// manifest, returns it and the entry point used.
- GURL GetStartURL(const LaunchParams& params, LaunchEntryPoint* used);
- ui::WindowShowState GetWindowShowStateWGT(const LaunchParams& params);
- ui::WindowShowState GetWindowShowStateXPK(const LaunchParams& params);
+ template <Package::Type> GURL GetStartURL();
+
+ template <Package::Type>
+ ui::WindowShowState GetWindowShowState(const LaunchParams& params);
GURL GetAbsoluteURLFromKey(const std::string& key);
RuntimeContext* runtime_context_;
Observer* observer_;
- // The entry point used as part of Launch().
- LaunchEntryPoint entry_point_used_;
+
std::map<std::string, std::string> name_perm_map_;
// Application's session permissions.
StoredPermissionMap permission_map_;
#include "xwalk/application/browser/application_service.h"
+#include <hash_set>
#include <set>
#include <string>
#include <vector>
-#include "base/containers/hash_tables.h"
-#include "base/files/file_enumerator.h"
#include "base/file_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "xwalk/application/browser/application.h"
-#include "xwalk/application/browser/application_system.h"
-#include "xwalk/application/common/application_storage.h"
-#include "xwalk/application/common/installer/package.h"
-#include "xwalk/application/common/installer/package_installer.h"
+#include "xwalk/application/common/application_manifest_constants.h"
#include "xwalk/application/common/application_file_util.h"
+#include "xwalk/application/common/id_util.h"
#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/runtime/browser/runtime.h"
-#include "xwalk/runtime/browser/xwalk_runner.h"
#include "xwalk/runtime/common/xwalk_paths.h"
#if defined(OS_TIZEN)
-#include "xwalk/application/browser/application_tizen.h"
+#include "xwalk/application/browser/application_service_tizen.h"
#endif
namespace xwalk {
namespace application {
-namespace {
-
-const base::FilePath::CharType kApplicationDataDirName[] =
- FILE_PATH_LITERAL("Storage/ext");
+ApplicationService::ApplicationService(RuntimeContext* runtime_context)
+ : runtime_context_(runtime_context) {
+}
-base::FilePath GetStoragePartitionPath(
- const base::FilePath& base_path, const std::string& app_id) {
-#if defined(OS_WIN)
- std::wstring application_id(app_id.begin(), app_id.end());
- return base_path.Append(kApplicationDataDirName).Append(application_id);
+scoped_ptr<ApplicationService> ApplicationService::Create(
+ RuntimeContext* runtime_context) {
+#if defined(OS_TIZEN)
+ return make_scoped_ptr<ApplicationService>(
+ new ApplicationServiceTizen(runtime_context));
#else
- return base_path.Append(kApplicationDataDirName).Append(app_id);
+ return make_scoped_ptr(new ApplicationService(runtime_context));
#endif
}
-void CollectUnusedStoragePartitions(RuntimeContext* context,
- ApplicationStorage* storage) {
- std::vector<std::string> app_ids;
- if (!storage->GetInstalledApplicationIDs(app_ids))
- return;
-
- scoped_ptr<base::hash_set<base::FilePath> > active_paths(
- new base::hash_set<base::FilePath>()); // NOLINT
-
- for (unsigned i = 0; i < app_ids.size(); ++i) {
- active_paths->insert(
- GetStoragePartitionPath(context->GetPath(), app_ids.at(i)));
- }
-
- content::BrowserContext::GarbageCollectStoragePartitions(
- context, active_paths.Pass(), base::Bind(&base::DoNothing));
-}
-
-} // namespace
-
-ApplicationService::ApplicationService(RuntimeContext* runtime_context,
- ApplicationStorage* app_storage)
- : runtime_context_(runtime_context),
- application_storage_(app_storage) {
- CollectUnusedStoragePartitions(runtime_context, app_storage);
-}
-
ApplicationService::~ApplicationService() {
}
return NULL;
}
-#if defined(OS_TIZEN)
- Application* application(new ApplicationTizen(application_data,
- runtime_context_, this));
-#else
- Application* application(new Application(application_data,
- runtime_context_, this));
-#endif
-
+ Application* application = Application::Create(application_data,
+ runtime_context_).release();
ScopedVector<Application>::iterator app_iter =
applications_.insert(applications_.end(), application);
return NULL;
}
+ application->set_observer(this);
+
FOR_EACH_OBSERVER(Observer, observers_,
DidLaunchApplication(application));
return application;
}
-Application* ApplicationService::Launch(
- const std::string& id, const Application::LaunchParams& params) {
- scoped_refptr<ApplicationData> application_data =
- application_storage_->GetApplicationData(id);
+Application* ApplicationService::LaunchFromUnpackedPath(
+ const base::FilePath& path, const Application::LaunchParams& params) {
+ std::string error;
+ scoped_refptr<ApplicationData> application_data;
+ if (!base::DirectoryExists(path)) {
+ LOG(ERROR) << "Invalid input parameter: " << path.AsUTF8Unsafe();
+ return NULL;
+ }
+
+ application_data =
+ LoadApplication(path, ApplicationData::LOCAL_DIRECTORY, &error);
+
if (!application_data) {
- LOG(ERROR) << "Application with id " << id << " is not installed.";
+ LOG(ERROR) << "Error occurred while trying to load application: "
+ << error;
return NULL;
}
return Launch(application_data, params);
}
-Application* ApplicationService::Launch(
+Application* ApplicationService::LaunchFromPackagePath(
const base::FilePath& path, const Application::LaunchParams& params) {
- if (!base::DirectoryExists(path))
+ scoped_ptr<Package> package = Package::Create(path);
+ if (!package || !package->IsValid()) {
+ LOG(ERROR) << "Failed to obtain valid package from "
+ << path.AsUTF8Unsafe();
return NULL;
+ }
+
+ base::FilePath tmp_dir, target_dir;
+ if (!GetTempDir(&tmp_dir)) {
+ LOG(ERROR) << "Failed to obtain system temp directory.";
+ return NULL;
+ }
std::string error;
- scoped_refptr<ApplicationData> application_data =
- LoadApplication(path, Manifest::COMMAND_LINE, &error);
+ scoped_refptr<ApplicationData> application_data;
+
+ base::CreateTemporaryDirInDir(tmp_dir, package->name(), &target_dir);
+ if (package->ExtractTo(target_dir)) {
+ std::string id = tmp_dir.BaseName().AsUTF8Unsafe();
+ application_data =
+ LoadApplication(
+ target_dir, id, ApplicationData::TEMP_DIRECTORY, &error);
+ }
if (!application_data) {
- LOG(ERROR) << "Error occurred while trying to launch application: "
+ LOG(ERROR) << "Error occurred while trying to load application: "
<< error;
return NULL;
}
return Launch(application_data, params);
}
+// Launch an application created from arbitrary url.
+// FIXME: This application should have the same strict permissions
+// as common browser apps.
+Application* ApplicationService::LaunchHostedURL(
+ const GURL& url, const Application::LaunchParams& params) {
+ const std::string& url_spec = url.spec();
+ if (url_spec.empty()) {
+ LOG(ERROR) << "Failed to launch application from the URL: " << url;
+ return NULL;
+ }
+
+ const std::string& app_id = GenerateId(url_spec);
+
+ base::DictionaryValue manifest;
+ // FIXME: define permissions!
+ manifest.SetString(application_manifest_keys::kStartURLKey, url_spec);
+ // FIXME: Why use URL as name?
+ manifest.SetString(application_manifest_keys::kNameKey, url_spec);
+ manifest.SetString(application_manifest_keys::kXWalkVersionKey, "0");
+
+ std::string error;
+ scoped_refptr<ApplicationData> app_data =
+ ApplicationData::Create(base::FilePath(),
+ ApplicationData::EXTERNAL_URL, manifest, app_id, &error);
+ DCHECK(app_data);
+
+ return Launch(app_data, params);
+}
+
namespace {
struct ApplicationRenderHostIDComparator {
CHECK(found != applications_.end());
FOR_EACH_OBSERVER(Observer, observers_,
WillDestroyApplication(application));
+ scoped_refptr<ApplicationData> app_data = application->data();
applications_.erase(found);
+
+ if (app_data->source_type() == ApplicationData::TEMP_DIRECTORY) {
+ LOG(INFO) << "Deleting the app temporary directory "
+ << app_data->Path().AsUTF8Unsafe();
+ content::BrowserThread::PostTask(content::BrowserThread::FILE,
+ FROM_HERE, base::Bind(base::IgnoreResult(&base::DeleteFile),
+ app_data->Path(), true /*recursive*/));
+ // FIXME: So far we simply clean up all the app persistent data,
+ // further we need to add an appropriate logic to handle it.
+ content::BrowserContext::GarbageCollectStoragePartitions(
+ runtime_context_,
+ make_scoped_ptr(new base::hash_set<base::FilePath>()),
+ base::Bind(&base::DoNothing));
+ }
+
#if !defined(SHARED_PROCESS_MODE)
if (applications_.empty()) {
base::MessageLoop::current()->PostTask(
#define XWALK_APPLICATION_BROWSER_APPLICATION_SERVICE_H_
#include <string>
+
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "xwalk/application/browser/application.h"
#include "xwalk/application/common/permission_policy_manager.h"
-#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/application/common/application_data.h"
namespace xwalk {
namespace application {
-class ApplicationStorage;
-class PackageInstaller;
-
-// The application service manages install, uninstall and updates of
-// applications.
+// The application service manages launch and termination of the applications.
class ApplicationService : public Application::Observer {
public:
// Client code may use this class (and register with AddObserver below) to
- // keep track of [un]installation of applications.
+ // keep track of applications life cycle.
class Observer {
public:
virtual void DidLaunchApplication(Application* app) {}
virtual ~Observer() {}
};
- ApplicationService(RuntimeContext* runtime_context,
- ApplicationStorage* app_storage);
virtual ~ApplicationService();
- Application* Launch(scoped_refptr<ApplicationData> application_data,
- const Application::LaunchParams& launch_params);
- // Launch an installed application using application id.
- Application* Launch(
- const std::string& id,
+ static scoped_ptr<ApplicationService> Create(
+ RuntimeContext* runtime_context);
+
+ // Launch an application using path to a local directory which
+ // contains manifest file of an unpacked application.
+ Application* LaunchFromUnpackedPath(
+ const base::FilePath& path,
const Application::LaunchParams& params = Application::LaunchParams());
- // Launch an unpacked application using path to a local directory which
- // contains manifest file.
- Application* Launch(
+
+ // Launch an application using path to its package file.
+ // Note: the given package is unpacked to a temporary folder,
+ // which is deleted after the application terminates.
+ Application* LaunchFromPackagePath(
const base::FilePath& path,
const Application::LaunchParams& params = Application::LaunchParams());
+ // Launch an application from an arbitrary URL.
+ // Creates a "dummy" application.
+ Application* LaunchHostedURL(
+ const GURL& url,
+ const Application::LaunchParams& params = Application::LaunchParams());
+
Application* GetApplicationByRenderHostID(int id) const;
Application* GetApplicationByID(const std::string& app_id) const;
const std::string& extension_name,
const std::string& perm_table);
+ protected:
+ explicit ApplicationService(RuntimeContext* runtime_context);
+
+ Application* Launch(scoped_refptr<ApplicationData> application_data,
+ const Application::LaunchParams& launch_params);
+
private:
// Implementation of Application::Observer.
virtual void OnApplicationTerminated(Application* app) OVERRIDE;
- xwalk::RuntimeContext* runtime_context_;
- ApplicationStorage* application_storage_;
+ RuntimeContext* runtime_context_;
ScopedVector<Application> applications_;
ObserverList<Observer> observers_;
--- /dev/null
+// 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/browser/application_service_tizen.h"
+
+#include <string>
+#include <vector>
+
+#include "xwalk/application/browser/application.h"
+#include "xwalk/application/common/application_storage.h"
+#include "xwalk/application/common/id_util.h"
+#include "xwalk/runtime/browser/runtime_context.h"
+
+namespace xwalk {
+
+namespace application {
+
+namespace {
+
+const base::FilePath::CharType kApplicationDataDirName[] =
+ FILE_PATH_LITERAL("Storage/ext");
+
+base::FilePath GetStoragePartitionPath(
+ const base::FilePath& base_path, const std::string& app_id) {
+ return base_path.Append(kApplicationDataDirName).Append(app_id);
+}
+
+void CollectUnusedStoragePartitions(RuntimeContext* context,
+ ApplicationStorage* storage) {
+ std::vector<std::string> app_ids;
+ if (!storage->GetInstalledApplicationIDs(app_ids))
+ return;
+
+ scoped_ptr<base::hash_set<base::FilePath> > active_paths(
+ new base::hash_set<base::FilePath>()); // NOLINT
+
+ for (unsigned i = 0; i < app_ids.size(); ++i) {
+ active_paths->insert(
+ GetStoragePartitionPath(context->GetPath(), app_ids.at(i)));
+ }
+
+ content::BrowserContext::GarbageCollectStoragePartitions(
+ context, active_paths.Pass(), base::Bind(&base::DoNothing));
+}
+
+} // namespace
+
+ApplicationServiceTizen::ApplicationServiceTizen(
+ RuntimeContext* runtime_context)
+ : ApplicationService(runtime_context),
+ application_storage_(new ApplicationStorage(runtime_context->GetPath())) {
+ CollectUnusedStoragePartitions(runtime_context, application_storage_.get());
+}
+
+ApplicationServiceTizen::~ApplicationServiceTizen() {
+}
+
+Application* ApplicationServiceTizen::LaunchFromAppID(
+ const std::string& id, const Application::LaunchParams& params) {
+ if (!IsValidApplicationID(id)) {
+ LOG(ERROR) << "The input parameter is not a valid app id: " << id;
+ return NULL;
+ }
+
+ scoped_refptr<ApplicationData> app_data =
+ application_storage_->GetApplicationData(id);
+ if (!app_data) {
+ LOG(ERROR) << "Application with id " << id << " is not installed.";
+ return NULL;
+ }
+
+ return Launch(app_data, params);
+}
+
+} // namespace application
+} // namespace xwalk
--- /dev/null
+// 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_BROWSER_APPLICATION_SERVICE_TIZEN_H_
+#define XWALK_APPLICATION_BROWSER_APPLICATION_SERVICE_TIZEN_H_
+
+#include <string>
+
+#include "xwalk/application/browser/application_service.h"
+
+namespace xwalk {
+
+namespace application {
+
+class ApplicationStorage;
+
+// The application service manages launch and termination of the applications.
+class ApplicationServiceTizen : public ApplicationService {
+ public:
+ virtual ~ApplicationServiceTizen();
+ // Launch an installed application using application id.
+ Application* LaunchFromAppID(
+ const std::string& id,
+ const Application::LaunchParams& params = Application::LaunchParams());
+
+ private:
+ friend class ApplicationService;
+ explicit ApplicationServiceTizen(RuntimeContext* runtime_context);
+ // Note : do not export app storage from this class! We need consider
+ // making ApplicationSystemTizen (owning the storage) instead.
+ scoped_ptr<ApplicationStorage> application_storage_;
+};
+
+inline ApplicationServiceTizen* ToApplicationServiceTizen(
+ ApplicationService* service) {
+ return static_cast<ApplicationServiceTizen*>(service);
+}
+
+} // namespace application
+} // namespace xwalk
+
+#endif // XWALK_APPLICATION_BROWSER_APPLICATION_SERVICE_TIZEN_H_
#include "net/base/filename_util.h"
#include "xwalk/application/browser/application.h"
#include "xwalk/application/browser/application_service.h"
-#include "xwalk/application/common/application_storage.h"
#include "xwalk/application/common/application_manifest_constants.h"
#include "xwalk/application/common/id_util.h"
#include "xwalk/application/extension/application_runtime_extension.h"
#include "xwalk/application/browser/application_system_linux.h"
#endif
+#if defined(OS_TIZEN)
+#include "xwalk/application/browser/application_service_tizen.h"
+#endif
+
namespace xwalk {
namespace application {
ApplicationSystem::ApplicationSystem(RuntimeContext* runtime_context)
: runtime_context_(runtime_context),
- application_storage_(new ApplicationStorage(runtime_context->GetPath())),
- application_service_(new ApplicationService(
- runtime_context,
- application_storage_.get())) {}
+ application_service_(ApplicationService::Create(
+ runtime_context)) {}
ApplicationSystem::~ApplicationSystem() {
}
return app_system.Pass();
}
-template <typename T>
-bool ApplicationSystem::LaunchWithCommandLineParam(
- const T& param, const base::CommandLine& cmd_line) {
- Application::LaunchParams launch_params;
- launch_params.force_fullscreen = cmd_line.HasSwitch(switches::kFullscreen);
- launch_params.remote_debugging =
- cmd_line.HasSwitch(switches::kRemoteDebuggingPort);
-
- return application_service_->Launch(param, launch_params);
-}
-
-// Launch an application created from arbitrary url.
-// FIXME: This application should have the same strict permissions
-// as common browser apps.
-template <>
-bool ApplicationSystem::LaunchWithCommandLineParam<GURL>(
- const GURL& url, const base::CommandLine& cmd_line) {
- std::string error;
- scoped_refptr<ApplicationData> application_data =
- ApplicationData::Create(url, &error);
- if (!application_data) {
- LOG(ERROR) << "Error occurred while trying to launch application: "
- << error;
- return false;
- }
+namespace {
- Application::LaunchParams launch_params;
- launch_params.force_fullscreen = cmd_line.HasSwitch(switches::kFullscreen);
- launch_params.entry_points = Application::StartURLKey;
- launch_params.remote_debugging =
+Application::LaunchParams launch_params(
+ const base::CommandLine& cmd_line) {
+ Application::LaunchParams params;
+ params.force_fullscreen = cmd_line.HasSwitch(switches::kFullscreen);
+ params.remote_debugging =
cmd_line.HasSwitch(switches::kRemoteDebuggingPort);
-
- return !!application_service_->Launch(application_data, launch_params);
+ return params;
}
+} // namespace
+
bool ApplicationSystem::LaunchFromCommandLine(
const base::CommandLine& cmd_line, const GURL& url,
bool& run_default_message_loop) { // NOLINT
+#if defined(OS_TIZEN)
// Handles raw app_id passed as first non-switch argument.
const base::CommandLine::StringVector& args = cmd_line.GetArgs();
if (!args.empty()) {
std::string app_id = std::string(args[0].begin(), args[0].end());
if (IsValidApplicationID(app_id)) {
- run_default_message_loop = LaunchWithCommandLineParam(app_id, cmd_line);
+ ApplicationServiceTizen* app_service_tizen =
+ ToApplicationServiceTizen(application_service_.get());
+ run_default_message_loop = app_service_tizen->LaunchFromAppID(
+ app_id, launch_params(cmd_line));
return true;
}
}
-
+#endif
if (!url.is_valid())
return false;
base::FilePath path;
- if (url.SchemeIsFile() &&
- net::FileURLToFilePath(url, &path) &&
- base::DirectoryExists(path)) { // Handles local directory.
- run_default_message_loop = LaunchWithCommandLineParam(path, cmd_line);
- } else { // Handles external URL.
- run_default_message_loop = LaunchWithCommandLineParam(url, cmd_line);
+ bool is_local = url.SchemeIsFile() && net::FileURLToFilePath(url, &path);
+ if (!is_local) { // Handles external URL.
+ run_default_message_loop = application_service_->LaunchHostedURL(
+ url, launch_params(cmd_line));
+ return true;
+ }
+
+ if (base::DirectoryExists(path)) { // Handles unpacked application.
+ run_default_message_loop = application_service_->LaunchFromUnpackedPath(
+ path, launch_params(cmd_line));
+ return true;
+ }
+
+ if (path.MatchesExtension(FILE_PATH_LITERAL(".xpk")) ||
+ path.MatchesExtension(FILE_PATH_LITERAL(".wgt"))) {
+ run_default_message_loop = application_service_->LaunchFromPackagePath(
+ path, launch_params(cmd_line));
+ return true;
}
- return true;
+ return false;
}
void ApplicationSystem::CreateExtensions(
namespace application {
class ApplicationService;
-class ApplicationServiceProvider;
-class ApplicationStorage;
// The ApplicationSystem manages the creation and destruction of services which
// related to applications' runtime model.
return application_service_.get();
}
- ApplicationStorage* application_storage() {
- return application_storage_.get();
- }
-
// Launches an application based on the given command line, there are
// different ways to inform which application should be launched
//
// (1) app_id from the binary name (used in Tizen);
- // (2) app_id passed in the command line;
+ // (2) app_id passed in the command line (used in Tizen);
// (3) launching a directory that contains an extracted package.
+ // (4) launching from the path to the packaged application file.
//
// The parameter `url` contains the current URL Crosswalk is considering to
// load, and the output parameter `run_default_message_loop` controls whether
// line, so the caller shouldn't try to load the url by itself.
bool LaunchFromCommandLine(const base::CommandLine& cmd_line,
const GURL& url,
- bool& run_default_message_loop_);
+ bool& run_default_message_loop_); // NOLINT
void CreateExtensions(content::RenderProcessHost* host,
extensions::XWalkExtensionVector* extensions);
explicit ApplicationSystem(RuntimeContext* runtime_context);
private:
- template <typename T>
- bool LaunchWithCommandLineParam(const T& param,
- const base::CommandLine& cmd_line);
// Note: initialization order matters.
- xwalk::RuntimeContext* runtime_context_;
- scoped_ptr<ApplicationStorage> application_storage_;
+ RuntimeContext* runtime_context_;
scoped_ptr<ApplicationService> application_service_;
DISALLOW_COPY_AND_ASSIGN(ApplicationSystem);
ApplicationTizen::ApplicationTizen(
scoped_refptr<ApplicationData> data,
- RuntimeContext* runtime_context,
- Application::Observer* observer)
- : Application(data, runtime_context, observer),
+ RuntimeContext* runtime_context)
+ : Application(data, runtime_context),
is_suspended_(false) {
#if defined(USE_OZONE)
ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
void Resume();
private:
- // We enforce ApplicationService ownership.
- friend class ApplicationService;
+ friend class Application;
ApplicationTizen(scoped_refptr<ApplicationData> data,
- RuntimeContext* context,
- Application::Observer* observer);
+ RuntimeContext* context);
virtual bool Launch(const LaunchParams& launch_params) OVERRIDE;
virtual base::FilePath GetSplashScreenPath() OVERRIDE;
#include "xwalk/application/common/application_data.h"
#include "xwalk/runtime/browser/xwalk_runner.h"
+#if defined(OS_TIZEN)
+#include "xwalk/application/browser/application_service_tizen.h"
+#endif
+
namespace {
// D-Bus Interface implemented by the manager object of running applications.
params.force_fullscreen = fullscreen;
params.remote_debugging = remote_debugging;
- Application* application;
- if (GURL(app_id_or_url).spec().empty()) {
- application = application_service_->Launch(app_id_or_url, params);
- } else {
- params.entry_points = Application::StartURLKey;
- std::string error;
- scoped_refptr<ApplicationData> application_data =
- ApplicationData::Create(GURL(app_id_or_url), &error);
- if (!application_data) {
- scoped_ptr<dbus::Response> response = CreateError(method_call, error);
- response_sender.Run(response.Pass());
- return;
- }
-
- application = application_service_->Launch(application_data, params);
- }
+ Application* application = NULL;
+ GURL url(app_id_or_url);
+ if (!url.spec().empty())
+ application = application_service_->LaunchHostedURL(url, params);
+
+#if defined(OS_TIZEN)
+ if (!application)
+ application = ToApplicationServiceTizen(
+ application_service_)->LaunchFromAppID(app_id_or_url, params);
+#endif
if (!application) {
scoped_ptr<dbus::Response> response =
// static
scoped_refptr<ApplicationData> ApplicationData::Create(
const base::FilePath& path,
- Manifest::SourceType source_type,
+ SourceType source_type,
const base::DictionaryValue& manifest_data,
const std::string& explicit_id,
std::string* error_message) {
DCHECK(error_message);
base::string16 error;
- scoped_ptr<xwalk::application::Manifest> manifest(
- new xwalk::application::Manifest(source_type,
- scoped_ptr<base::DictionaryValue>(manifest_data.DeepCopy())));
+ scoped_ptr<Manifest> manifest(new Manifest(
+ scoped_ptr<base::DictionaryValue>(manifest_data.DeepCopy())));
if (!manifest->ValidateManifest(error_message))
return NULL;
- scoped_refptr<ApplicationData> application = new ApplicationData(path,
- manifest.Pass());
- if (!application->Init(explicit_id, &error)) {
+ scoped_refptr<ApplicationData> app_data =
+ new ApplicationData(path, source_type, manifest.Pass());
+ if (!app_data->Init(explicit_id, &error)) {
*error_message = base::UTF16ToUTF8(error);
return NULL;
}
- return application;
-}
-
-// static
-scoped_refptr<ApplicationData> ApplicationData::Create(
- const GURL& url,
- std::string* error_message) {
- const std::string& url_spec = url.spec();
- DCHECK(!url_spec.empty());
- const std::string& app_id = GenerateId(url_spec);
-
- base::DictionaryValue manifest;
- // FIXME: define permissions!
- manifest.SetString(application_manifest_keys::kStartURLKey, url_spec);
- // FIXME: Why use URL as name?
- manifest.SetString(application_manifest_keys::kNameKey, url_spec);
- manifest.SetString(application_manifest_keys::kXWalkVersionKey, "0");
- scoped_refptr<ApplicationData> application_data =
- ApplicationData::Create(base::FilePath(), Manifest::COMMAND_LINE,
- manifest, app_id, error_message);
-
- return application_data;
+ return app_data;
}
// static
manifest_data_[key] = linked_ptr<ManifestData>(data);
}
-Manifest::SourceType ApplicationData::GetSourceType() const {
- return manifest_->GetSourceType();
-}
-
const std::string& ApplicationData::ID() const {
return manifest_->GetApplicationID();
}
return "";
}
-bool ApplicationData::IsPlatformApp() const {
- return manifest_->IsPackaged();
-}
-
bool ApplicationData::IsHostedApp() const {
return GetManifest()->IsHosted();
}
ApplicationData::ApplicationData(const base::FilePath& path,
- scoped_ptr<xwalk::application::Manifest> manifest)
+ SourceType source_type, scoped_ptr<Manifest> manifest)
: manifest_version_(0),
manifest_(manifest.release()),
- finished_parsing_manifest_(false) {
+ finished_parsing_manifest_(false),
+ source_type_(source_type) {
DCHECK(path.empty() || path.IsAbsolute());
path_ = path;
if (manifest_->HasPath(widget_keys::kWidgetKey))
// static
GURL ApplicationData::GetResourceURL(const GURL& application_url,
const std::string& relative_path) {
- DCHECK(application_url.SchemeIs(xwalk::application::kApplicationScheme));
+ DCHECK(application_url.SchemeIs(kApplicationScheme));
DCHECK_EQ("/", application_url.path());
std::string path = relative_path;
#include "url/gurl.h"
#include "xwalk/application/common/manifest.h"
#include "xwalk/application/common/permission_types.h"
+#include "xwalk/application/common/package/package.h"
namespace base {
class DictionaryValue;
class ApplicationData : public base::RefCountedThreadSafe<ApplicationData> {
public:
+ // Where an application was loaded from.
+ enum SourceType {
+ INTERNAL, // From internal application registry.
+ LOCAL_DIRECTORY, // From a persistently stored unpacked application
+ TEMP_DIRECTORY, // From a temporary folder
+ EXTERNAL_URL // From an arbitrary URL
+ };
+
struct ManifestData;
struct ApplicationIdCompare {
};
static scoped_refptr<ApplicationData> Create(const base::FilePath& path,
- Manifest::SourceType source_type,
+ SourceType source_type,
const base::DictionaryValue& manifest_data,
const std::string& explicit_id,
std::string* error_message);
- static scoped_refptr<ApplicationData> Create(const GURL& url,
- std::string* error_message);
-
Manifest::Type GetType() const;
// Returns an absolute url to a resource inside of an application. The
const base::FilePath& Path() const { return path_; }
void SetPath(const base::FilePath& path) { path_ = path; }
const GURL& URL() const { return application_url_; }
- Manifest::SourceType GetSourceType() const;
+ SourceType source_type() const { return source_type_; }
const std::string& ID() const;
#if defined(OS_TIZEN)
std::string GetPackageID() const;
const base::Time& install_time() const { return install_time_; }
// App-related.
- bool IsPlatformApp() const;
bool IsHostedApp() const;
// Permission related.
friend class base::RefCountedThreadSafe<ApplicationData>;
friend class ApplicationStorageImpl;
- ApplicationData(const base::FilePath& path,
- scoped_ptr<Manifest> manifest);
+ ApplicationData(const base::FilePath& path, SourceType source_type,
+ scoped_ptr<Manifest> manifest);
virtual ~ApplicationData();
// Initialize the application from a parsed manifest.
// The package type, wgt or xpk.
Package::Type package_type_;
+ // The source the application was loaded from.
+ SourceType source_type_;
+
DISALLOW_COPY_AND_ASSIGN(ApplicationData);
};
#include "net/base/file_stream.h"
#include "third_party/libxml/src/include/libxml/tree.h"
#include "ui/base/l10n/l10n_util.h"
-#include "xwalk/application/common/installer/package.h"
#include "xwalk/application/common/application_data.h"
#include "xwalk/application/common/application_manifest_constants.h"
#include "xwalk/application/common/constants.h"
scoped_refptr<ApplicationData> LoadApplication(
const base::FilePath& application_path,
- Manifest::SourceType source_type,
+ ApplicationData::SourceType source_type,
std::string* error) {
Package::Type package_type;
if (!GetPackageType(application_path, &package_type, error))
scoped_refptr<ApplicationData> LoadApplication(
const base::FilePath& application_path,
const std::string& application_id,
- Manifest::SourceType source_type,
+ ApplicationData::SourceType source_type,
std::string* error) {
Package::Type package_type;
#if defined(OS_TIZEN)
scoped_refptr<ApplicationData> LoadApplication(
const base::FilePath& application_path,
const std::string& application_id,
- Manifest::SourceType source_type,
+ ApplicationData::SourceType source_type,
Package::Type package_type,
std::string* error) {
scoped_ptr<base::DictionaryValue> manifest(
#include <map>
#include "base/memory/ref_counted.h"
-#include "xwalk/application/common/installer/package.h"
-#include "xwalk/application/common/manifest.h"
-
+#include "xwalk/application/common/application_data.h"
class GURL;
// on failure, with a description of the error in |error|.
scoped_refptr<ApplicationData> LoadApplication(
const base::FilePath& application_root,
- Manifest::SourceType source_type,
+ ApplicationData::SourceType source_type,
std::string* error);
// The same as LoadApplication except use the provided |application_id|.
scoped_refptr<ApplicationData> LoadApplication(
const base::FilePath& application_root,
const std::string& application_id,
- Manifest::SourceType source_type,
+ ApplicationData::SourceType source_type,
std::string* error);
scoped_refptr<ApplicationData> LoadApplication(
const base::FilePath& application_root,
const std::string& application_id,
- Manifest::SourceType source_type,
+ ApplicationData::SourceType source_type,
Package::Type package_type,
std::string* error);
std::string error;
scoped_refptr<ApplicationData> application(LoadApplication(
- install_dir, Manifest::COMMAND_LINE, &error));
+ install_dir, ApplicationData::LOCAL_DIRECTORY, &error));
ASSERT_TRUE(application != NULL);
EXPECT_EQ("The first application that I made.", application->Description());
}
std::string error;
scoped_refptr<ApplicationData> application(LoadApplication(
- install_dir, Manifest::COMMAND_LINE, &error));
+ install_dir, ApplicationData::LOCAL_DIRECTORY, &error));
ASSERT_TRUE(application == NULL);
ASSERT_FALSE(error.empty());
ASSERT_STREQ("Manifest file is missing or unreadable.", error.c_str());
std::string error;
scoped_refptr<ApplicationData> application(LoadApplication(
- install_dir, Manifest::COMMAND_LINE, &error));
+ install_dir, ApplicationData::LOCAL_DIRECTORY, &error));
ASSERT_TRUE(application == NULL);
ASSERT_FALSE(error.empty());
ASSERT_STREQ("Manifest is not valid JSON."
static scoped_refptr<ApplicationData> LoadApplicationManifest(
base::DictionaryValue* manifest,
const base::FilePath& manifest_dir,
- Manifest::SourceType location,
+ ApplicationData::SourceType location,
int extra_flags,
std::string* error) {
scoped_refptr<ApplicationData> application = ApplicationData::Create(
static scoped_refptr<ApplicationData> LoadApplicationManifest(
const std::string& manifest_value,
const base::FilePath& manifest_dir,
- Manifest::SourceType location,
+ ApplicationData::SourceType location,
int extra_flags,
std::string* error) {
JSONStringValueSerializer serializer(manifest_value);
"}", non_ascii_file.c_str());
std::string error;
scoped_refptr<ApplicationData> application = LoadApplicationManifest(
- kManifest, temp.path(), Manifest::COMMAND_LINE, 0, &error);
+ kManifest, temp.path(), ApplicationData::LOCAL_DIRECTORY, 0, &error);
ASSERT_TRUE(application.get()) << error;
}
return application_manifest_keys::kXWalkVersionKey;
}
-const char* GetLaunchLocalPathKey(Package::Type package_type) {
- if (package_type == Package::WGT)
- return application_widget_keys::kLaunchLocalPathKey;
-
- return application_manifest_keys::kLaunchLocalPathKey;
-}
-
const char* GetCSPKey(Package::Type package_type) {
if (package_type == Package::WGT)
return application_widget_keys::kCSPKey;
#define XWALK_APPLICATION_COMMON_APPLICATION_MANIFEST_CONSTANTS_H_
#include "xwalk/application/common/manifest.h"
+#include "xwalk/application/common/package/package.h"
// Keys used in JSON representation of applications.
namespace xwalk {
namespace application_manifest_keys {
} // namespace application_manifest_errors
namespace application {
-
-typedef application::Manifest Manifest;
const char* GetNameKey(Package::Type type);
-const char* GetLaunchLocalPathKey(Package::Type type);
const char* GetCSPKey(Package::Type type);
#if defined(OS_TIZEN)
const char* GetTizenAppIdKey(Package::Type type);
#ifndef XWALK_APPLICATION_COMMON_APPLICATION_STORAGE_H_
#define XWALK_APPLICATION_COMMON_APPLICATION_STORAGE_H_
-#include <map>
#include <string>
#include <vector>
std::string error;
scoped_refptr<ApplicationData> application =
ApplicationData::Create(base::FilePath::FromUTF8Unsafe(path),
- Manifest::INTERNAL,
+ ApplicationData::INTERNAL,
*manifest,
it.key(),
&error);
scoped_refptr<ApplicationData> app_data =
ApplicationData::Create(
base::FilePath::FromUTF8Unsafe(path),
- Manifest::INTERNAL,
+ ApplicationData::INTERNAL,
*manifest,
id,
&error);
base::FilePath app_path = GetApplicationPath(app_id);
std::string error_str;
- return LoadApplication(app_path, app_id, Manifest::INTERNAL, &error_str);
+ return LoadApplication(
+ app_path, app_id, ApplicationData::INTERNAL, &error_str);
}
bool ApplicationStorageImpl::GetInstalledApplicationIDs(
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
base::FilePath(),
- Manifest::INVALID_TYPE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest,
"",
&error);
std::string error;
scoped_refptr<ApplicationData> application =
ApplicationData::Create(base::FilePath(),
- Manifest::INTERNAL,
+ ApplicationData::INTERNAL,
manifest,
"",
&error);
std::string error;
scoped_refptr<ApplicationData> application =
ApplicationData::Create(base::FilePath(),
- Manifest::INTERNAL,
+ ApplicationData::INTERNAL,
manifest,
"",
&error);
manifest.SetString("a", "c");
scoped_refptr<ApplicationData> new_application =
ApplicationData::Create(base::FilePath(),
- Manifest::INTERNAL,
+ ApplicationData::INTERNAL,
manifest,
"",
&error);
std::string error;
scoped_refptr<ApplicationData> application =
ApplicationData::Create(base::FilePath(),
- Manifest::INTERNAL,
+ ApplicationData::INTERNAL,
manifest,
"",
&error);
// We persist location values in the preferences, so this is a sanity test that
// someone doesn't accidentally change them.
TEST(ApplicationTest, LocationValuesTest) {
- ASSERT_EQ(0, Manifest::INVALID_TYPE);
- ASSERT_EQ(1, Manifest::INTERNAL);
- ASSERT_EQ(2, Manifest::COMMAND_LINE);
+ ASSERT_EQ(0, ApplicationData::INTERNAL);
+ ASSERT_EQ(1, ApplicationData::LOCAL_DIRECTORY);
+ ASSERT_EQ(2, ApplicationData::TEMP_DIRECTORY);
+ ASSERT_EQ(3, ApplicationData::EXTERNAL_URL);
}
} // namespace application
+++ /dev/null
-// 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_INSTALLER_PACKAGE_INSTALLER_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_PACKAGE_INSTALLER_H_
-
-#include <string>
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-
-namespace xwalk {
-namespace application {
-
-class ApplicationData;
-class ApplicationStorage;
-
-class PackageInstaller {
- public:
- static scoped_ptr<PackageInstaller> Create(ApplicationStorage* storage);
-
- virtual ~PackageInstaller();
-
- 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);
- void ContinueUnfinishedTasks();
-
- virtual void SetQuiet(bool quiet);
- virtual void SetInstallationKey(const std::string& key);
-
- protected:
- explicit PackageInstaller(ApplicationStorage* storage);
-
- virtual std::string PrepareUninstallationID(const std::string& id);
-
- // Those to be overriden to implement platform specific logic.
- virtual bool PlatformInstall(ApplicationData* data);
- virtual bool PlatformUninstall(ApplicationData* data);
- virtual bool PlatformUpdate(ApplicationData* updated_data);
-
- ApplicationStorage* storage_;
-};
-
-} // namespace application
-} // namespace xwalk
-
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_PACKAGE_INSTALLER_H_
+++ /dev/null
-// 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/installer/package_installer_tizen.h"
-
-#include <sys/types.h>
-#include <pwd.h>
-#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"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/path_service.h"
-#include "base/command_line.h"
-#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_file_util.h"
-#include "xwalk/application/common/application_manifest_constants.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/application_storage.h"
-#include "xwalk/application/common/installer/tizen/packageinfo_constants.h"
-#include "xwalk/application/common/id_util.h"
-#include "xwalk/runtime/common/xwalk_paths.h"
-
-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");
-
-const base::FilePath kDefaultIcon(
- "/usr/share/icons/default/small/crosswalk.png");
-
-const std::string kServicePrefix("xwalk-service.");
-const std::string kAppIdPrefix("xwalk.");
-
-void WriteMetaDataElement(
- XmlWriter& writer, // NOLINT
- 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,
- const base::FilePath& xml_path) {
- if (!base::PathExists(app_dir) &&
- !base::CreateDirectory(app_dir))
- return false;
-
- std::string package_id =
- xwalk::application::AppIdToPkgId(application->ID());
-
- base::FilePath execute_path =
- app_dir.AppendASCII("bin/").AppendASCII(application->ID());
- std::string stripped_name = application->Name();
-
- FILE* file = base::OpenFile(xml_path, "w");
-
- XmlWriter xml_writer;
- xml_writer.StartWriting();
- xml_writer.StartElement("manifest");
- xml_writer.AddAttribute("xmlns", "http://tizen.org/ns/packages");
- xml_writer.AddAttribute("package", package_id);
- xml_writer.AddAttribute("type", "wgt");
- xml_writer.AddAttribute("version", application->VersionString());
- xml_writer.WriteElement("label", application->Name());
- xml_writer.WriteElement("description", application->Description());
-
- xml_writer.StartElement("ui-application");
- xml_writer.AddAttribute("appid", application->ID());
- xml_writer.AddAttribute("exec", execute_path.MaybeAsASCII());
- xml_writer.AddAttribute("type", "webapp");
- 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
- xml_writer.WriteElement("icon",
- kServicePrefix + application->ID() + ".png");
- xml_writer.EndElement(); // Ends "ui-application"
-
- xml_writer.EndElement(); // Ends "manifest" element.
- xml_writer.StopWriting();
-
- base::WriteFile(xml_path,
- xml_writer.GetWrittenString().c_str(),
- xml_writer.GetWrittenString().size());
-
- base::CloseFile(file);
- LOG(INFO) << "Converting manifest.json into "
- << xml_path.BaseName().MaybeAsASCII()
- << " for installation. [DONE]";
- return true;
-}
-
-bool CreateAppSymbolicLink(const base::FilePath& app_dir,
- const std::string& app_id) {
- base::FilePath execute_path =
- app_dir.AppendASCII("bin/").AppendASCII(app_id);
-
- if (!base::CreateDirectory(execute_path.DirName())) {
- LOG(ERROR) << "Could not create directory '"
- << execute_path.DirName().value() << "'.";
- return false;
- }
-
- if (!base::CreateSymbolicLink(kXWalkLauncherBinary, execute_path)) {
- LOG(ERROR) << "Could not create symbolic link to launcher from '"
- << execute_path.value() << "'.";
- return false;
- }
- return true;
-}
-
-} // namespace
-
-namespace xwalk {
-namespace application {
-
-PackageInstallerTizen::PackageInstallerTizen(ApplicationStorage* storage)
- : PackageInstaller(storage) {
-}
-
-void PackageInstallerTizen::SetQuiet(bool quiet) {
- quiet_ = quiet;
-}
-
-void PackageInstallerTizen::SetInstallationKey(const std::string& key) {
- key_ = key;
-}
-
-std::string PackageInstallerTizen::PrepareUninstallationID(
- const std::string& id) {
- // this function fix pkg_id to app_id
- // if installer was launched with pkg_id
- if (IsValidPkgID(id)) {
- LOG(INFO) << "The package id is given " << id << " Will find app_id...";
- std::string appid = PkgIdToAppId(id);
- if (!appid.empty())
- return appid;
- }
- return id;
-}
-
-bool PackageInstallerTizen::PlatformInstall(ApplicationData* app_data) {
- std::string app_id(app_data->ID());
- base::FilePath data_dir;
- CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));
-
- base::FilePath app_dir =
- data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
- base::FilePath xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
- app_id + std::string(info::kXmlExtension));
-
- std::string icon_name;
- if (!app_data->GetManifest()->GetString(
- GetIcon128Key(app_data->GetPackageType()), &icon_name))
- LOG(WARNING) << "'icon' not included in manifest";
-
- // This will clean everything inside '<data dir>/<app id>'.
- FileDeleter app_dir_cleaner(app_dir, true);
-
- if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, xml_path)) {
- LOG(ERROR) << "Failed to create XML metadata file '"
- << xml_path.value() << "'.";
- return false;
- }
-
- if (!CreateAppSymbolicLink(app_dir, app_id)) {
- LOG(ERROR) << "Failed to create symbolic link for " << app_id;
- return false;
- }
-
- base::FilePath icon =
- icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);
-
- CommandLine cmdline(kPkgHelper);
- cmdline.AppendSwitchASCII("--install", app_id);
- cmdline.AppendSwitchPath("--xml", xml_path);
- cmdline.AppendSwitchPath("--icon", icon);
- if (quiet_)
- cmdline.AppendSwitch("-q");
- if (!key_.empty()) {
- cmdline.AppendSwitchASCII("--key", key_);
- }
-
- int exit_code;
- std::string output;
-
- if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
- LOG(ERROR) << "Could not launch the installation helper process.";
- return false;
- }
-
- if (exit_code != 0) {
- LOG(ERROR) << "Could not install application: "
- << output << " (" << exit_code << ")";
- return false;
- }
-
- app_dir_cleaner.Dismiss();
-
- return true;
-}
-
-bool PackageInstallerTizen::PlatformUninstall(ApplicationData* app_data) {
- bool result = true;
- std::string app_id(app_data->ID());
- base::FilePath data_dir;
- CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));
-
- CommandLine cmdline(kPkgHelper);
- cmdline.AppendSwitchASCII("--uninstall", app_id);
- if (quiet_)
- cmdline.AppendSwitch("-q");
- if (!key_.empty()) {
- cmdline.AppendSwitchASCII("--key", key_);
- }
-
- int exit_code;
- std::string output;
-
- if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
- LOG(ERROR) << "Could not launch installer helper";
- result = false;
- }
-
- if (exit_code != 0) {
- LOG(ERROR) << "Could not uninstall application: "
- << output << " (" << exit_code << ")";
- result = false;
- }
-
- base::FilePath app_dir =
- data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
- if (!base::DeleteFile(app_dir, true)) {
- LOG(ERROR) << "Could not remove directory '" << app_dir.value() << "'";
- result = false;
- }
-
- base::FilePath xml_path = data_dir.AppendASCII(
- app_id + std::string(info::kXmlExtension));
- if (!base::DeleteFile(xml_path, false)) {
- LOG(ERROR) << "Could not remove file '" << xml_path.value() << "'";
- result = false;
- }
-
- return result;
-}
-
-bool PackageInstallerTizen::PlatformUpdate(ApplicationData* app_data) {
- std::string app_id(app_data->ID());
- base::FilePath data_dir;
- CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));
-
- base::FilePath app_dir =
- data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
- base::FilePath new_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
- app_id + ".new" + std::string(info::kXmlExtension));
-
- std::string icon_name;
- if (!app_data->GetManifest()->GetString(
- GetIcon128Key(app_data->GetPackageType()), &icon_name))
- LOG(WARNING) << "'icon' not included in manifest";
-
- // This will clean everything inside '<data dir>/<app id>' and the new XML.
- FileDeleter app_dir_cleaner(app_dir, true);
- FileDeleter new_xml_cleaner(new_xml_path, true);
-
- if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, new_xml_path)) {
- LOG(ERROR) << "Could not create new XML metadata file '"
- << new_xml_path.value() << "'.";
- return false;
- }
-
- if (!CreateAppSymbolicLink(app_dir, app_id))
- return false;
-
- base::FilePath icon =
- icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);
-
- CommandLine cmdline(kPkgHelper);
- cmdline.AppendSwitchASCII("--update", app_id);
- cmdline.AppendSwitchPath("--xml", new_xml_path);
- cmdline.AppendSwitchPath("--icon", icon);
- if (quiet_)
- cmdline.AppendSwitch("-q");
- if (!key_.empty()) {
- cmdline.AppendSwitchASCII("--key", key_);
- }
-
- int exit_code;
- std::string output;
-
- if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
- LOG(ERROR) << "Could not launch installer helper";
- return false;
- }
-
- if (exit_code != 0) {
- LOG(ERROR) << "Could not update application: "
- << output << " (" << exit_code << ")";
- return false;
- }
-
- base::FilePath old_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
- app_id + std::string(info::kXmlExtension));
- base::Move(new_xml_path, old_xml_path);
- app_dir_cleaner.Dismiss();
- return true;
-}
-
-} // namespace application
-} // namespace xwalk
+++ /dev/null
-// 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_INSTALLER_PACKAGE_INSTALLER_TIZEN_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_PACKAGE_INSTALLER_TIZEN_H_
-
-#include <string>
-
-#include "xwalk/application/common/installer/package_installer.h"
-
-namespace xwalk {
-namespace application {
-
-class PackageInstallerTizen : public PackageInstaller {
- public:
- explicit PackageInstallerTizen(ApplicationStorage* storage);
-
- void SetQuiet(bool quiet) OVERRIDE;
- void SetInstallationKey(const std::string& key) OVERRIDE;
-
- protected:
- std::string PrepareUninstallationID(const std::string& id) OVERRIDE;
-
- virtual bool PlatformInstall(ApplicationData* data) OVERRIDE;
- virtual bool PlatformUninstall(ApplicationData* data) OVERRIDE;
- virtual bool PlatformUpdate(ApplicationData* data) OVERRIDE;
-
- private:
- bool quiet_;
- std::string key_;
-};
-
-} // namespace application
-} // namespace xwalk
-
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_PACKAGE_INSTALLER_TIZEN_H_
} // namespace
-Manifest::Manifest(SourceType source_type,
- scoped_ptr<base::DictionaryValue> value)
- : source_type_(source_type),
- data_(value.Pass()),
+Manifest::Manifest(scoped_ptr<base::DictionaryValue> value)
+ : data_(value.Pass()),
i18n_data_(new base::DictionaryValue),
type_(TYPE_UNKNOWN) {
// FIXME: Hosted apps can contain start_url. Below is wrong.
Manifest* Manifest::DeepCopy() const {
Manifest* manifest = new Manifest(
- source_type_, scoped_ptr<base::DictionaryValue>(data_->DeepCopy()));
+ scoped_ptr<base::DictionaryValue>(data_->DeepCopy()));
manifest->SetApplicationID(application_id_);
return manifest;
}
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/values.h"
-#include "xwalk/application/common/installer/package.h"
namespace xwalk {
namespace application {
// properties of the manifest using ManifestFeatureProvider.
class Manifest {
public:
- // Where an application was loaded from.
- enum SourceType {
- INVALID_TYPE,
- INTERNAL, // Load from internal application registry.
- COMMAND_LINE, // Load from an unpacked application from command line.
- NUM_TYPES
- };
-
enum Type {
TYPE_UNKNOWN = 0,
TYPE_HOSTED_APP,
TYPE_PACKAGED_APP
};
- Manifest(SourceType source_type, scoped_ptr<base::DictionaryValue> value);
+ explicit Manifest(scoped_ptr<base::DictionaryValue> value);
~Manifest();
const std::string& GetApplicationID() const { return application_id_; }
void SetApplicationID(const std::string& id) { application_id_ = id; }
- SourceType GetSourceType() const { return source_type_; }
-
// Returns false and |error| will be non-empty if the manifest is malformed.
// |warnings| will be populated if there are keys in the manifest that cannot
// be specified by the application type.
// A persistent, globally unique ID. An application's ID is used in things
// like directory structures and URLs, and is expected to not change across
- // versions. It is generated as a SHA-256 hash of the application's public
- // key, or as a hash of the path in the case of unpacked applications.
+ // versions.
std::string application_id_;
#if defined(OS_TIZEN)
std::string package_id_;
#endif
- // The source the application was loaded from.
- SourceType source_type_;
-
// The underlying dictionary representation of the manifest.
scoped_ptr<base::DictionaryValue> data_;
scoped_ptr<base::DictionaryValue> i18n_data_;
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
base::FilePath(),
- Manifest::INVALID_TYPE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest,
"",
&error);
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
base::FilePath(),
- Manifest::INVALID_TYPE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest_a,
"",
&error);
application = ApplicationData::Create(
base::FilePath(),
- Manifest::INVALID_TYPE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest_a,
"",
&error);
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
base::FilePath(),
- Manifest::COMMAND_LINE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest,
"",
&error);
scoped_refptr<ApplicationData> CreateApplication() {
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
- base::FilePath(), Manifest::INVALID_TYPE, manifest, "", &error);
+ base::FilePath(), ApplicationData::LOCAL_DIRECTORY,
+ manifest, "", &error);
return application;
}
scoped_refptr<ApplicationData> CreateApplication() {
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
- base::FilePath(), Manifest::INVALID_TYPE, manifest, "", &error);
+ base::FilePath(), ApplicationData::LOCAL_DIRECTORY,
+ manifest, "", &error);
return application;
}
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
base::FilePath(),
- Manifest::INVALID_TYPE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest,
"",
&error);
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
base::FilePath(),
- Manifest::INVALID_TYPE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest,
"",
&error);
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
base::FilePath(),
- Manifest::INVALID_TYPE,
+ ApplicationData::LOCAL_DIRECTORY,
manifest,
"",
&error);
scoped_refptr<ApplicationData> CreateApplication() {
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
- base::FilePath(), Manifest::INVALID_TYPE, manifest, "", &error);
+ base::FilePath(), ApplicationData::LOCAL_DIRECTORY,
+ manifest, "", &error);
return application;
}
class WidgetHandlerTest: public testing::Test {
public:
scoped_refptr<ApplicationData> CreateApplication(
- base::DictionaryValue &manifest) {
+ const base::DictionaryValue& manifest) {
std::string error;
scoped_refptr<ApplicationData> application = ApplicationData::Create(
- base::FilePath(), Manifest::INVALID_TYPE, manifest, "", &error);
+ base::FilePath(), ApplicationData::LOCAL_DIRECTORY,
+ manifest, "", &error);
return application;
}
manifest_value->Set(key, value);
else
manifest_value->Remove(key, NULL);
- manifest->reset(new Manifest(Manifest::COMMAND_LINE,
- manifest_value.Pass()));
+ manifest->reset(new Manifest(manifest_value.Pass()));
}
std::string default_value_;
manifest_value->SetString("unknown_key", "foo");
scoped_ptr<Manifest> manifest(
- new Manifest(Manifest::COMMAND_LINE, manifest_value.Pass()));
+ new Manifest(manifest_value.Pass()));
std::string error;
EXPECT_TRUE(manifest->ValidateManifest(&error));
EXPECT_TRUE(error.empty());
value->SetString(keys::kXWalkVersionKey, "1");
scoped_ptr<Manifest> manifest(
- new Manifest(Manifest::COMMAND_LINE, value.Pass()));
+ new Manifest(value.Pass()));
std::string error;
EXPECT_TRUE(manifest->ValidateManifest(&error));
EXPECT_TRUE(error.empty());
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/package.h"
+#include "xwalk/application/common/package/package.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "third_party/zlib/google/zip.h"
#include "xwalk/application/common/id_util.h"
-#include "xwalk/application/common/installer/wgt_package.h"
-#include "xwalk/application/common/installer/xpk_package.h"
+#include "xwalk/application/common/package/wgt_package.h"
+#include "xwalk/application/common/package/xpk_package.h"
namespace xwalk {
namespace application {
Package::Package(const base::FilePath& source_path)
: source_path_(source_path),
is_extracted_(false),
- is_valid_(false) {
+ is_valid_(false),
+ name_(source_path_.BaseName().AsUTF8Unsafe()) {
}
Package::~Package() {
// static
scoped_ptr<Package> Package::Create(const base::FilePath& source_path) {
if (source_path.MatchesExtension(FILE_PATH_LITERAL(".xpk"))) {
- scoped_ptr<Package> package(new XPKPackage(source_path));
- if (!package->IsValid())
- LOG(ERROR) << "Package not valid";
- return package.Pass();
- } else if (source_path.MatchesExtension(FILE_PATH_LITERAL(".wgt"))) {
- scoped_ptr<Package> package(new WGTPackage(source_path));
- return package.Pass();
+ scoped_ptr<Package> package(new XPKPackage(source_path));
+ return package.Pass();
+ }
+ if (source_path.MatchesExtension(FILE_PATH_LITERAL(".wgt"))) {
+ scoped_ptr<Package> package(new WGTPackage(source_path));
+ return package.Pass();
}
LOG(ERROR) << "Invalid package type. Only .xpk/.wgt supported now";
return scoped_ptr<Package>();
}
-bool Package::Extract(base::FilePath* target_path) {
+bool Package::ExtractToTemporaryDir(base::FilePath* target_path) {
if (is_extracted_) {
*target_path = temp_dir_.path();
return true;
return true;
}
+bool Package::ExtractTo(const base::FilePath& target_path) {
+ if (!DirectoryExists(target_path)) {
+ LOG(ERROR) << "The directory " << target_path.MaybeAsASCII()
+ << "does not exist";
+ return false;
+ }
+ if (!IsDirectoryEmpty(target_path)) {
+ LOG(ERROR) << "The directory " << target_path.MaybeAsASCII()
+ << "is not empty.";
+ return false;
+ }
+ if (!zip::Unzip(source_path_, target_path)) {
+ LOG(ERROR) << "An error occurred during package extraction";
+ return false;
+ }
+
+ return true;
+}
+
// Create a temporary directory to decompress the zipped package file.
// As the package information might already exists under data_path,
// it's safer to extract the XPK/WGT file into a temporary directory first.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_COMMON_INSTALLER_PACKAGE_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_PACKAGE_H_
+#ifndef XWALK_APPLICATION_COMMON_PACKAGE_PACKAGE_H_
+#define XWALK_APPLICATION_COMMON_PACKAGE_PACKAGE_H_
#include <string>
#include <vector>
virtual ~Package();
bool IsValid() const { return is_valid_; }
const std::string& Id() const { return id_; }
+ const std::string& name() const { return name_; }
Type type() const { return type_; }
// Factory method for creating a package
static scoped_ptr<Package> Create(const base::FilePath& path);
// The function will unzip the XPK/WGT file and return the target path where
// to decompress by the parameter |target_path|.
- virtual bool Extract(base::FilePath* target_path);
+ virtual bool ExtractToTemporaryDir(base::FilePath* result_path);
+ // The function will unzip the XPK/WGT file to the given folder.
+ virtual bool ExtractTo(const base::FilePath& target_path);
protected:
explicit Package(const base::FilePath& source_path);
- scoped_ptr<base::ScopedFILE> file_;
- bool is_valid_;
- std::string id_;
// Unzipping of the zipped file happens in a temporary directory
bool CreateTempDirectory();
+ scoped_ptr<base::ScopedFILE> file_;
+
+ bool is_valid_;
base::FilePath source_path_;
+ std::string id_;
+ std::string name_;
// Temporary directory for unpacking.
base::ScopedTempDir temp_dir_;
// Represent if the package has been extracted.
} // namespace application
} // namespace xwalk
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_PACKAGE_H_
+#endif // XWALK_APPLICATION_COMMON_PACKAGE_PACKAGE_H_
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/package.h"
+#include "xwalk/application/common/package/package.h"
#include "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
SetupPackage("good.xpk");
EXPECT_FALSE(package_->Id().empty());
base::FilePath path;
- EXPECT_TRUE(package_->Extract(&path));
+ EXPECT_TRUE(package_->ExtractToTemporaryDir(&path));
EXPECT_TRUE(base::DirectoryExists(path));
EXPECT_TRUE(temp_dir_.Set(path));
}
TEST_F(PackageTest, BadMagicString) {
SetupPackage("bad_magic.xpk");
base::FilePath path;
- EXPECT_FALSE(package_->Extract(&path));
+ EXPECT_FALSE(package_->ExtractToTemporaryDir(&path));
}
TEST_F(PackageTest, BadSignature) {
SetupPackage("bad_signature.xpk");
base::FilePath path;
- EXPECT_FALSE(package_->Extract(&path));
+ EXPECT_FALSE(package_->ExtractToTemporaryDir(&path));
}
TEST_F(PackageTest, NoMagicHeader) {
SetupPackage("no_magic_header.xpk");
base::FilePath path;
- EXPECT_FALSE(package_->Extract(&path));
+ EXPECT_FALSE(package_->ExtractToTemporaryDir(&path));
}
TEST_F(PackageTest, BadXPKPackageExtension) {
TEST_F(PackageTest, BadUnzipFile) {
SetupPackage("bad_zip.xpk");
base::FilePath path;
- EXPECT_FALSE(package_->Extract(&path));
+ EXPECT_FALSE(package_->ExtractToTemporaryDir(&path));
}
} // namespace application
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/wgt_package.h"
+#include "xwalk/application/common/package/wgt_package.h"
#include "base/file_util.h"
#include "base/files/scoped_file.h"
#include "third_party/libxml/chromium/libxml_utils.h"
#include "xwalk/application/common/id_util.h"
-#include "xwalk/application/common/installer/tizen/signature_validator.h"
+
+#if defined(OS_TIZEN)
+#include "xwalk/application/common/tizen/signature_validator.h"
+#endif
namespace xwalk {
namespace application {
return;
type_ = WGT;
base::FilePath extracted_path;
- if (!Extract(&extracted_path))
+ // FIXME : we should not call 'extract' here!
+ if (!ExtractToTemporaryDir(&extracted_path))
return;
XmlReader xml;
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_COMMON_INSTALLER_WGT_PACKAGE_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_WGT_PACKAGE_H_
+#ifndef XWALK_APPLICATION_COMMON_PACKAGE_WGT_PACKAGE_H_
+#define XWALK_APPLICATION_COMMON_PACKAGE_WGT_PACKAGE_H_
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
-#include "xwalk/application/common/installer/package.h"
+#include "xwalk/application/common/package/package.h"
namespace xwalk {
namespace application {
} // namespace application
} // namespace xwalk
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_WGT_PACKAGE_H_
+#endif // XWALK_APPLICATION_COMMON_PACKAGE_WGT_PACKAGE_H_
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/xpk_package.h"
+#include "xwalk/application/common/package/xpk_package.h"
#include "base/file_util.h"
#include "base/files/scoped_file.h"
std::string(reinterpret_cast<char*>(&key_.front()), key_.size());
id_ = GenerateId(public_key);
}
- return;
}
bool XPKPackage::VerifySignature() {
return true;
}
-bool XPKPackage::Extract(base::FilePath* target_path) {
+bool XPKPackage::ExtractToTemporaryDir(base::FilePath* target_path) {
if (is_extracted_) {
*target_path = temp_dir_.path();
return true;
return false;
}
- return Package::Extract(target_path);
+ return Package::ExtractToTemporaryDir(target_path);
}
} // namespace application
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_COMMON_INSTALLER_XPK_PACKAGE_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_XPK_PACKAGE_H_
+#ifndef XWALK_APPLICATION_COMMON_PACKAGE_XPK_PACKAGE_H_
+#define XWALK_APPLICATION_COMMON_PACKAGE_XPK_PACKAGE_H_
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
-#include "xwalk/application/common/installer/package.h"
+#include "xwalk/application/common/package/package.h"
namespace xwalk {
namespace application {
};
virtual ~XPKPackage();
explicit XPKPackage(const base::FilePath& path);
- virtual bool Extract(base::FilePath* target_path) OVERRIDE;
+ virtual bool ExtractToTemporaryDir(base::FilePath* target_path) OVERRIDE;
private:
// verify the signature in the xpk package
} // namespace application
} // namespace xwalk
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_XPK_PACKAGE_H_
+#endif // XWALK_APPLICATION_COMMON_PACKAGE_XPK_PACKAGE_H_
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/signature_data.h"
+#include "xwalk/application/common/tizen/signature_data.h"
#include "base/strings/utf_string_conversions.h"
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_COMMON_INSTALLER_SIGNATURE_DATA_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_SIGNATURE_DATA_H_
+#ifndef XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_DATA_H_
+#define XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_DATA_H_
#include <list>
#include <set>
} // namespace application
} // namespace xwalk
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_SIGNATURE_DATA_H_
+#endif // XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_DATA_H_
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/signature_parser.h"
+#include "xwalk/application/common/tizen/signature_parser.h"
#include <list>
#include <set>
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_COMMON_INSTALLER_SIGNATURE_PARSER_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_SIGNATURE_PARSER_H_
+#ifndef XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_PARSER_H_
+#define XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_PARSER_H_
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
-#include "xwalk/application/common/installer/signature_data.h"
+#include "xwalk/application/common/tizen/signature_data.h"
namespace xwalk {
namespace application {
} // namespace application
} // namespace xwalk
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_SIGNATURE_PARSER_H_
+#endif // XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_PARSER_H_
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/tizen/signature_validator.h"
+#include "xwalk/application/common/tizen/signature_validator.h"
#include <set>
#include <string>
#include "libxml/parser.h"
#include "libxml/xmlschemas.h"
#include "third_party/re2/re2/re2.h"
-#include "xwalk/application/common/installer/signature_data.h"
-#include "xwalk/application/common/installer/signature_parser.h"
+#include "xwalk/application/common/tizen/signature_data.h"
+#include "xwalk/application/common/tizen/signature_parser.h"
namespace {
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_SIGNATURE_VALIDATOR_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_SIGNATURE_VALIDATOR_H_
+#ifndef XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_VALIDATOR_H_
+#define XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_VALIDATOR_H_
#include "base/files/file_path.h"
} // namespace application
} // namespace xwalk
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_SIGNATURE_VALIDATOR_H_
+#endif // XWALK_APPLICATION_COMMON_TIZEN_SIGNATURE_VALIDATOR_H_
'permission_policy_manager.h',
'permission_types.h',
'signature_types.h',
-
- 'installer/package.h',
- 'installer/package.cc',
- 'installer/package_installer.cc',
- 'installer/package_installer.h',
- 'installer/signature_data.h',
- 'installer/signature_data.cc',
- 'installer/signature_parser.h',
- 'installer/signature_parser.cc',
- 'installer/wgt_package.h',
- 'installer/wgt_package.cc',
- 'installer/xpk_package.cc',
- 'installer/xpk_package.h',
+ 'package/package.h',
+ 'package/package.cc',
+ 'package/wgt_package.h',
+ 'package/wgt_package.cc',
+ 'package/xpk_package.cc',
+ 'package/xpk_package.h',
],
'conditions': [
['tizen==1', {
'manifest_handlers/tizen_setting_handler.h',
'manifest_handlers/tizen_splash_screen_handler.cc',
'manifest_handlers/tizen_splash_screen_handler.h',
- 'installer/package_installer_tizen.cc',
- 'installer/package_installer_tizen.h',
- 'installer/tizen/packageinfo_constants.cc',
- 'installer/tizen/packageinfo_constants.h',
- 'installer/tizen/signature_validator.cc',
- 'installer/tizen/signature_validator.h',
'tizen/package_path.cc',
'tizen/package_path.h',
+ 'tizen/signature_data.h',
+ 'tizen/signature_data.cc',
+ 'tizen/signature_parser.h',
+ 'tizen/signature_parser.cc',
+ 'tizen/signature_validator.cc',
+ 'tizen/signature_validator.h',
+
],
}, {
'sources': [
}
IN_PROC_BROWSER_TEST_F(ApplicationBrowserTest, ApiTest) {
- Application* app = application_sevice()->Launch(
+ Application* app = application_sevice()->LaunchFromUnpackedPath(
test_data_dir_.Append(FILE_PATH_LITERAL("api")));
ASSERT_TRUE(app);
test_runner_->WaitForTestNotification();
ApplicationService* service = application_sevice();
const size_t currently_running_count = service->active_applications().size();
// Launch the first app.
- Application* app1 = service->Launch(
+ Application* app1 = service->LaunchFromUnpackedPath(
test_data_dir_.Append(FILE_PATH_LITERAL("dummy_app1")));
ASSERT_TRUE(app1);
// Wait for app is fully loaded.
// Verify that no new App instance was created, if one exists
// with the same ID.
- Application* failed_app1 = service->Launch(
+ Application* failed_app1 = service->LaunchFromUnpackedPath(
test_data_dir_.Append(FILE_PATH_LITERAL("dummy_app1")));
ASSERT_FALSE(failed_app1);
// Launch the second app.
- Application* app2 = service->Launch(
+ Application* app2 = service->LaunchFromUnpackedPath(
test_data_dir_.Append(FILE_PATH_LITERAL("dummy_app2")));
ASSERT_TRUE(app2);
// Wait for app is fully loaded.
};
IN_PROC_BROWSER_TEST_F(ApplicationTestApiTest, TestApiTest) {
- Application* app = application_sevice()->Launch(
+ Application* app = application_sevice()->LaunchFromUnpackedPath(
test_data_dir_.Append(FILE_PATH_LITERAL("testapi")));
ASSERT_TRUE(app);
test_runner_->WaitForTestNotification();
{
- 'targets': [
- {
- 'target_name': 'xwalkctl',
- 'type': 'executable',
- 'product_name': 'xwalkctl',
- 'dependencies': [
- '../../../application/common/xwalk_application_common.gypi:xwalk_application_common_lib',
- '../../../build/system.gyp:gio',
- '../../../../build/linux/system.gyp:dbus',
- '../../../../dbus/dbus.gyp:dbus',
- ],
- 'include_dirs': [
- '../../../..',
- ],
- 'sources': [
- 'dbus_connection.cc',
- 'dbus_connection.h',
- 'xwalkctl_main.cc',
- # TODO(t.iwanek) fix me - this duplicates compilation of those files
- '../../../runtime/common/xwalk_paths.cc',
- '../../../runtime/common/xwalk_paths.h',
- '../../../runtime/common/xwalk_system_locale.cc',
- '../../../runtime/common/xwalk_system_locale.h',
- ],
- 'conditions' : [
- ['tizen==1', {
- 'dependencies': [
- '../../../build/system.gyp:tizen',
- ],
- 'sources': [
- 'xwalk_tizen_user.cc',
- 'xwalk_tizen_user.h',
- ],
- }],
- ],
- },
+ 'targets': [
{
'target_name': 'xwalk_launcher',
'type': 'executable',
'sources': [
'xwalk_launcher_tizen.cc',
'xwalk_launcher_tizen.h',
- 'xwalk_tizen_user.cc',
- 'xwalk_tizen_user.h',
+ '../tizen/xwalk_tizen_user.cc',
+ '../tizen/xwalk_tizen_user.h',
],
}],
],
#if defined(OS_TIZEN)
#include "url/gurl.h"
#include "xwalk/application/tools/linux/xwalk_launcher_tizen.h"
-#include "xwalk/application/tools/linux/xwalk_tizen_user.h"
+#include "xwalk/application/tools/tizen/xwalk_tizen_user.h"
#endif
static const char* xwalk_service_name = "org.crosswalkproject.Runtime1";
scoped_ptr<xwalk::application::Package> package =
xwalk::application::Package::Create(base::FilePath(pkg_path));
- package->Extract(&unpacked_dir);
+ package->ExtractToTemporaryDir(&unpacked_dir);
std::string app_id = package->Id();
std::string error;
scoped_refptr<xwalk::application::ApplicationData> app_data = LoadApplication(
- unpacked_dir, app_id, xwalk::application::Manifest::COMMAND_LINE,
+ unpacked_dir, app_id, xwalk::application::ApplicationData::TEMP_DIRECTORY,
package->type(), &error);
return app_data;
}
keyvalue="$2"
shift
;;
- "-r") echo "Reinstall not supported"
- exit 128 # ErrorNotSupportRDSUpdate == 128
- ;; #TODO(t.iwanek) fix me - sending signals for reinstall option
+ "-r") option="-r"
+ id="$2"
+ ;;
esac
shift
done
char* install_option = NULL;
char* update_option = NULL;
char* uninstall_option = NULL;
+char* reinstall_option = NULL;
char* operation_key = NULL;
char* xml_path = NULL;
char* icon_path = NULL;
"Path of the application to be updated", "APPID" },
{ "uninstall", 'd', 0, G_OPTION_ARG_STRING, &uninstall_option,
"Uninstall the application with this appid", "APPID" },
+ { "reinstall", 'r', 0, G_OPTION_ARG_STRING, &reinstall_option,
+ "Path of the application to be reinstalled", "APPID" },
{ "key", 'k', 0, G_OPTION_ARG_STRING, &operation_key,
"Unique operation key", "KEY" },
{ "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
appId = uninstall_option;
} else if (update_option) {
appId = update_option;
+ } else if (reinstall_option) {
+ appId = reinstall_option;
} else {
- fprintf(stderr, "Use: --install, --uninstall or --update\n");
+ fprintf(stderr, "Use: --install, --uninstall, --update or --reinstall\n");
exit(1);
}
}
result = helper.UpdateApplication(xml_path, icon_path);
+ } else if (reinstall_option) {
+ if (operation_key) {
+ pkgmgr_argv[0] = "-r";
+ pkgmgr_argv[1] = reinstall_option; // this value is ignored by pkgmgr
+ helper.InitializePkgmgrSignal((quiet ? 5 : 4), pkgmgr_argv);
+ }
+
+ result = helper.ReinstallApplication();
}
// Convention is to return 0 on success.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/package_installer.h"
+#include "xwalk/application/tools/tizen/xwalk_package_installer.h"
#include <sys/types.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <pkgmgr/pkgmgr_parser.h>
+
#include <algorithm>
#include <map>
#include <string>
#include "base/command_line.h"
#include "base/process/launch.h"
#include "base/version.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
#include "xwalk/application/common/application_data.h"
#include "xwalk/application/common/application_file_util.h"
#include "xwalk/application/common/application_manifest_constants.h"
-#include "xwalk/application/common/permission_policy_manager.h"
#include "xwalk/application/common/application_storage.h"
#include "xwalk/application/common/id_util.h"
-#include "xwalk/application/common/installer/tizen/packageinfo_constants.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/permission_policy_manager.h"
+#include "xwalk/application/tools/tizen/xwalk_packageinfo_constants.h"
#include "xwalk/runtime/common/xwalk_paths.h"
-#if defined(OS_TIZEN)
-#include "xwalk/application/common/installer/package_installer_tizen.h"
-#endif
+namespace info = application_packageinfo_constants;
-namespace xwalk {
-namespace application {
+using xwalk::application::ApplicationData;
+using xwalk::application::ApplicationStorage;
+using xwalk::application::FileDeleter;
+using xwalk::application::Package;
namespace {
+const base::FilePath::CharType kApplicationsDir[] =
+ FILE_PATH_LITERAL("applications");
+
+const base::FilePath::CharType kInstallTempDir[] =
+ FILE_PATH_LITERAL("install_temp");
+
+const base::FilePath::CharType kUpdateTempDir[] =
+ FILE_PATH_LITERAL("update_temp");
+
+namespace widget_keys = xwalk::application_widget_keys;
+
+const base::FilePath kPkgHelper("/usr/bin/xwalk-pkg-helper");
+
+const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");
+
+const base::FilePath kDefaultIcon(
+ "/usr/share/icons/default/small/crosswalk.png");
+
+const std::string kServicePrefix("xwalk-service.");
+const std::string kAppIdPrefix("xwalk.");
+
bool CopyDirectoryContents(const base::FilePath& from,
const base::FilePath& to) {
base::FileEnumerator iter(from, false,
return true;
}
-const base::FilePath::CharType kApplicationsDir[] =
- FILE_PATH_LITERAL("applications");
+void WriteMetaDataElement(
+ XmlWriter& writer, // NOLINT
+ 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();
+ }
+}
-const base::FilePath::CharType kInstallTempDir[] =
- FILE_PATH_LITERAL("install_temp");
+bool GeneratePkgInfoXml(xwalk::application::ApplicationData* application,
+ const std::string& icon_name,
+ const base::FilePath& app_dir,
+ const base::FilePath& xml_path) {
+ if (!base::PathExists(app_dir) &&
+ !base::CreateDirectory(app_dir))
+ return false;
+
+ std::string package_id =
+ xwalk::application::AppIdToPkgId(application->ID());
+
+ base::FilePath execute_path =
+ app_dir.AppendASCII("bin/").AppendASCII(application->ID());
+ std::string stripped_name = application->Name();
+
+ FILE* file = base::OpenFile(xml_path, "w");
+
+ XmlWriter xml_writer;
+ xml_writer.StartWriting();
+ xml_writer.StartElement("manifest");
+ xml_writer.AddAttribute("xmlns", "http://tizen.org/ns/packages");
+ xml_writer.AddAttribute("package", package_id);
+ xml_writer.AddAttribute("type", "wgt");
+ xml_writer.AddAttribute("version", application->VersionString());
+ xml_writer.WriteElement("label", application->Name());
+ xml_writer.WriteElement("description", application->Description());
+
+ xml_writer.StartElement("ui-application");
+ xml_writer.AddAttribute("appid", application->ID());
+ xml_writer.AddAttribute("exec", execute_path.MaybeAsASCII());
+ xml_writer.AddAttribute("type", "webapp");
+ 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
+ xml_writer.WriteElement("icon",
+ kServicePrefix + application->ID() + ".png");
+ xml_writer.EndElement(); // Ends "ui-application"
+
+ xml_writer.EndElement(); // Ends "manifest" element.
+ xml_writer.StopWriting();
+
+ base::WriteFile(xml_path,
+ xml_writer.GetWrittenString().c_str(),
+ xml_writer.GetWrittenString().size());
+
+ base::CloseFile(file);
+ LOG(INFO) << "Converting manifest.json into "
+ << xml_path.BaseName().MaybeAsASCII()
+ << " for installation. [DONE]";
+ return true;
+}
+
+bool CreateAppSymbolicLink(const base::FilePath& app_dir,
+ const std::string& app_id) {
+ base::FilePath execute_path =
+ app_dir.AppendASCII("bin/").AppendASCII(app_id);
+
+ if (!base::CreateDirectory(execute_path.DirName())) {
+ LOG(ERROR) << "Could not create directory '"
+ << execute_path.DirName().value() << "'.";
+ return false;
+ }
+
+ if (!base::CreateSymbolicLink(kXWalkLauncherBinary, execute_path)) {
+ LOG(ERROR) << "Could not create symbolic link to launcher from '"
+ << execute_path.value() << "'.";
+ return false;
+ }
+ return true;
+}
-const base::FilePath::CharType kUpdateTempDir[] =
- FILE_PATH_LITERAL("update_temp");
} // namespace
PackageInstaller::PackageInstaller(ApplicationStorage* storage)
- : storage_(storage) {
+ : storage_(storage),
+ quiet_(false) {
}
PackageInstaller::~PackageInstaller() {
scoped_ptr<PackageInstaller> PackageInstaller::Create(
ApplicationStorage* storage) {
-#if defined(OS_TIZEN)
- return scoped_ptr<PackageInstaller>(new PackageInstallerTizen(storage));
-#else
return scoped_ptr<PackageInstaller>(new PackageInstaller(storage));
-#endif
}
void PackageInstaller::SetQuiet(bool quiet) {
+ quiet_ = quiet;
}
void PackageInstaller::SetInstallationKey(const std::string& key) {
+ key_ = key;
}
-std::string PackageInstaller::PrepareUninstallationID(const std::string& id) {
+std::string PackageInstaller::PrepareUninstallationID(
+ const std::string& id) {
+ // this function fix pkg_id to app_id
+ // if installer was launched with pkg_id
+ if (xwalk::application::IsValidPkgID(id)) {
+ LOG(INFO) << "The package id is given " << id << " Will find app_id...";
+ std::string appid = xwalk::application::PkgIdToAppId(id);
+ if (!appid.empty())
+ return appid;
+ }
return id;
}
-bool PackageInstaller::PlatformInstall(ApplicationData* data) {
+bool PackageInstaller::PlatformInstall(ApplicationData* app_data) {
+ std::string app_id(app_data->ID());
+ base::FilePath data_dir;
+ CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));
+
+ base::FilePath app_dir =
+ data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
+ base::FilePath xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
+ app_id + std::string(info::kXmlExtension));
+
+ std::string icon_name;
+ if (!app_data->GetManifest()->GetString(
+ GetIcon128Key(app_data->GetPackageType()), &icon_name))
+ LOG(WARNING) << "'icon' not included in manifest";
+
+ // This will clean everything inside '<data dir>/<app id>'.
+ FileDeleter app_dir_cleaner(app_dir, true);
+
+ if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, xml_path)) {
+ LOG(ERROR) << "Failed to create XML metadata file '"
+ << xml_path.value() << "'.";
+ return false;
+ }
+
+ if (!CreateAppSymbolicLink(app_dir, app_id)) {
+ LOG(ERROR) << "Failed to create symbolic link for " << app_id;
+ return false;
+ }
+
+ base::FilePath icon =
+ icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);
+
+ CommandLine cmdline(kPkgHelper);
+ cmdline.AppendSwitchASCII("--install", app_id);
+ cmdline.AppendSwitchPath("--xml", xml_path);
+ cmdline.AppendSwitchPath("--icon", icon);
+ if (quiet_)
+ cmdline.AppendSwitch("-q");
+ if (!key_.empty()) {
+ cmdline.AppendSwitchASCII("--key", key_);
+ }
+
+ int exit_code;
+ std::string output;
+
+ if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
+ LOG(ERROR) << "Could not launch the installation helper process.";
+ return false;
+ }
+
+ if (exit_code != 0) {
+ LOG(ERROR) << "Could not install application: "
+ << output << " (" << exit_code << ")";
+ return false;
+ }
+
+ app_dir_cleaner.Dismiss();
+
return true;
}
-bool PackageInstaller::PlatformUninstall(ApplicationData* data) {
+bool PackageInstaller::PlatformUninstall(ApplicationData* app_data) {
+ bool result = true;
+ std::string app_id(app_data->ID());
+ base::FilePath data_dir;
+ CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));
+
+ CommandLine cmdline(kPkgHelper);
+ cmdline.AppendSwitchASCII("--uninstall", app_id);
+ if (quiet_)
+ cmdline.AppendSwitch("-q");
+ if (!key_.empty()) {
+ cmdline.AppendSwitchASCII("--key", key_);
+ }
+
+ int exit_code;
+ std::string output;
+
+ if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
+ LOG(ERROR) << "Could not launch installer helper";
+ result = false;
+ }
+
+ if (exit_code != 0) {
+ LOG(ERROR) << "Could not uninstall application: "
+ << output << " (" << exit_code << ")";
+ result = false;
+ }
+
+ base::FilePath app_dir =
+ data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
+ if (!base::DeleteFile(app_dir, true)) {
+ LOG(ERROR) << "Could not remove directory '" << app_dir.value() << "'";
+ result = false;
+ }
+
+ base::FilePath xml_path = data_dir.AppendASCII(
+ app_id + std::string(info::kXmlExtension));
+ if (!base::DeleteFile(xml_path, false)) {
+ LOG(ERROR) << "Could not remove file '" << xml_path.value() << "'";
+ result = false;
+ }
+
+ return result;
+}
+
+bool PackageInstaller::PlatformUpdate(ApplicationData* app_data) {
+ std::string app_id(app_data->ID());
+ base::FilePath data_dir;
+ CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));
+
+ base::FilePath app_dir =
+ data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
+ base::FilePath new_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
+ app_id + ".new" + std::string(info::kXmlExtension));
+
+ std::string icon_name;
+ if (!app_data->GetManifest()->GetString(
+ GetIcon128Key(app_data->GetPackageType()), &icon_name))
+ LOG(WARNING) << "'icon' not included in manifest";
+
+ // This will clean everything inside '<data dir>/<app id>' and the new XML.
+ FileDeleter app_dir_cleaner(app_dir, true);
+ FileDeleter new_xml_cleaner(new_xml_path, true);
+
+ if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, new_xml_path)) {
+ LOG(ERROR) << "Could not create new XML metadata file '"
+ << new_xml_path.value() << "'.";
+ return false;
+ }
+
+ if (!CreateAppSymbolicLink(app_dir, app_id))
+ return false;
+
+ base::FilePath icon =
+ icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);
+
+ CommandLine cmdline(kPkgHelper);
+ cmdline.AppendSwitchASCII("--update", app_id);
+ cmdline.AppendSwitchPath("--xml", new_xml_path);
+ cmdline.AppendSwitchPath("--icon", icon);
+ if (quiet_)
+ cmdline.AppendSwitch("-q");
+ if (!key_.empty()) {
+ cmdline.AppendSwitchASCII("--key", key_);
+ }
+
+ int exit_code;
+ std::string output;
+
+ if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
+ LOG(ERROR) << "Could not launch installer helper";
+ return false;
+ }
+
+ if (exit_code != 0) {
+ LOG(ERROR) << "Could not update application: "
+ << output << " (" << exit_code << ")";
+ return false;
+ }
+
+ base::FilePath old_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
+ app_id + std::string(info::kXmlExtension));
+ base::Move(new_xml_path, old_xml_path);
+ app_dir_cleaner.Dismiss();
return true;
}
-bool PackageInstaller::PlatformUpdate(ApplicationData* updated_data) {
+bool PackageInstaller::PlatformReinstall(const base::FilePath& path) {
+ CommandLine cmdline(kPkgHelper);
+ cmdline.AppendSwitchPath("--reinstall", path);
+ if (quiet_)
+ cmdline.AppendSwitch("-q");
+ if (!key_.empty()) {
+ cmdline.AppendSwitchASCII("--key", key_);
+ }
+
+ int exit_code;
+ std::string output;
+
+ if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
+ LOG(ERROR) << "Could not launch installer helper";
+ return false;
+ }
+
+ if (exit_code != 0) {
+ LOG(ERROR) << "Could not reinstall application: "
+ << output << " (" << exit_code << ")";
+ return false;
+ }
+
return true;
}
package = Package::Create(tmp_path.path());
if (!package->IsValid())
return false;
- package->Extract(&unpacked_dir);
+ package->ExtractToTemporaryDir(&unpacked_dir);
app_id = package->Id();
} else {
unpacked_dir = path;
std::string error;
scoped_refptr<ApplicationData> app_data = LoadApplication(
- unpacked_dir, app_id, Manifest::COMMAND_LINE,
+ unpacked_dir, app_id, ApplicationData::LOCAL_DIRECTORY,
package->type(), &error);
if (!app_data) {
LOG(ERROR) << "Error during application installation: " << error;
// FIXME: Probably should be removed, as we should not handle permissions
// inside XWalk.
- PermissionPolicyManager permission_policy_handler;
+ xwalk::application::PermissionPolicyManager permission_policy_handler;
if (!permission_policy_handler.
InitApplicationPermission(app_data)) {
LOG(ERROR) << "Application permission data is invalid";
bool PackageInstaller::Update(const std::string& app_id,
const base::FilePath& path) {
- if (!IsValidApplicationID(app_id)) {
+ if (!xwalk::application::IsValidApplicationID(app_id)) {
LOG(ERROR) << "The given application id " << app_id << " is invalid.";
return false;
}
return false;
}
- if (!package->Extract(&unpacked_dir))
+ if (!package->ExtractToTemporaryDir(&unpacked_dir))
return false;
std::string error;
scoped_refptr<ApplicationData> new_app_data =
LoadApplication(unpacked_dir,
app_id,
- Manifest::COMMAND_LINE,
+ ApplicationData::TEMP_DIRECTORY,
package->type(),
&error);
if (!new_app_data) {
}
if (
-#if defined(OS_TIZEN)
// For Tizen WGT package, downgrade to a lower version or reinstall
// is permitted when using Tizen WRT, Crosswalk runtime need to follow
// this behavior on Tizen platform.
package->type() != Package::WGT &&
-#endif
old_app_data->Version()->CompareTo(
*(new_app_data->Version())) >= 0) {
LOG(INFO) << "The version number of new XPK/WGT package "
new_app_data = LoadApplication(app_dir,
app_id,
- Manifest::COMMAND_LINE,
+ ApplicationData::LOCAL_DIRECTORY,
package->type(),
&error);
if (!new_app_data) {
bool PackageInstaller::Uninstall(const std::string& id) {
std::string app_id = PrepareUninstallationID(id);
- if (!IsValidApplicationID(app_id)) {
+ if (!xwalk::application::IsValidApplicationID(app_id)) {
LOG(ERROR) << "The given application id " << app_id << " is invalid.";
return false;
}
return result;
}
+bool PackageInstaller::Reinstall(const base::FilePath& path) {
+ return PlatformReinstall(path);
+}
+
void PackageInstaller::ContinueUnfinishedTasks() {
base::FilePath config_dir;
CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &config_dir));
}
}
}
-
-} // namespace application
-} // namespace xwalk
--- /dev/null
+// 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_PACKAGE_INSTALLER_H_
+#define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PACKAGE_INSTALLER_H_
+
+#include <string>
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace xwalk {
+namespace application {
+
+class ApplicationData;
+class ApplicationStorage;
+
+} // namespace application
+} // namespace xwalk
+
+class PackageInstaller {
+ public:
+ static scoped_ptr<PackageInstaller> Create(
+ xwalk::application::ApplicationStorage* storage);
+
+ ~PackageInstaller();
+
+ 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 Reinstall(const base::FilePath& path);
+
+ void ContinueUnfinishedTasks();
+
+ void SetQuiet(bool quiet);
+ void SetInstallationKey(const std::string& key);
+
+ protected:
+ explicit PackageInstaller(xwalk::application::ApplicationStorage* storage);
+
+ std::string PrepareUninstallationID(const std::string& id);
+
+ bool PlatformInstall(xwalk::application::ApplicationData* data);
+ bool PlatformUninstall(xwalk::application::ApplicationData* data);
+ bool PlatformUpdate(xwalk::application::ApplicationData* updated_data);
+ bool PlatformReinstall(const base::FilePath& path);
+
+ xwalk::application::ApplicationStorage* storage_;
+ bool quiet_;
+ std::string key_;
+};
+
+
+
+#endif // XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PACKAGE_INSTALLER_H_
// Value for update.
const char PKGMGR_START_UPDATE[] = "update";
+// Value for update.
+const char PKGMGR_START_REINSTALL[] = "reinstall";
+
// Notification about end of installation with status.
const char PKGMGR_END_KEY[] = "end";
return ret;
}
+bool PackageInstallerHelper::ReinstallApplication() {
+ SendSignal(PKGMGR_START_KEY, PKGMGR_START_REINSTALL);
+ // FIXME not implemented, just send signal abotu failure
+ SendSignal(PKGMGR_END_KEY, ToEndStatus(false));
+ return false;
+}
+
bool PackageInstallerHelper::InstallApplicationInternal(
const std::string& xmlpath,
const std::string& iconpath) {
bool UninstallApplication();
bool UpdateApplication(const std::string& xmlpath,
const std::string& iconpath);
+ bool ReinstallApplication();
private:
bool InstallApplicationInternal(const std::string& xmlpath,
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/application/common/installer/tizen/packageinfo_constants.h"
+#include "xwalk/application/tools/tizen/xwalk_packageinfo_constants.h"
-namespace xwalk {
namespace application_packageinfo_constants {
const base::FilePath::CharType kAppDir[] =
const char kSeparator[] = ".";
} // namespace application_packageinfo_constants
-} // namespace xwalk
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_PACKAGEINFO_CONSTANTS_H_
-#define XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_PACKAGEINFO_CONSTANTS_H_
+#ifndef XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PACKAGEINFO_CONSTANTS_H_
+#define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PACKAGEINFO_CONSTANTS_H_
#include "base/files/file_path.h"
#include "base/basictypes.h"
-namespace xwalk {
namespace application_packageinfo_constants {
extern const base::FilePath::CharType kAppDir[];
extern const base::FilePath::CharType kAppDBPath[];
extern const char kXmlExtension[];
extern const char kSeparator[];
} // namespace application_packageinfo_constants
-} // namespace xwalk
-#endif // XWALK_APPLICATION_COMMON_INSTALLER_TIZEN_PACKAGEINFO_CONSTANTS_H_
+#endif // XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PACKAGEINFO_CONSTANTS_H_
{
'targets': [
{
+ 'target_name': 'xwalkctl',
+ 'type': 'executable',
+ 'product_name': 'xwalkctl',
+ 'dependencies': [
+ '../../../application/common/xwalk_application_common.gypi:xwalk_application_common_lib',
+ '../../../build/system.gyp:gio',
+ '../../../../build/linux/system.gyp:dbus',
+ '../../../../dbus/dbus.gyp:dbus',
+ '../../../build/system.gyp:tizen',
+ ],
+ 'include_dirs': [
+ '../../../..',
+ ],
+ 'sources': [
+ 'xwalkctl_main.cc',
+ 'xwalk_package_installer.cc',
+ 'xwalk_package_installer.h',
+ 'xwalk_packageinfo_constants.cc',
+ 'xwalk_packageinfo_constants.h',
+ 'xwalk_tizen_user.cc',
+ 'xwalk_tizen_user.h',
+ # TODO(t.iwanek) fix me - this duplicates compilation of those files
+ '../../../runtime/common/xwalk_paths.cc',
+ '../../../runtime/common/xwalk_paths.h',
+ '../../../runtime/common/xwalk_system_locale.cc',
+ '../../../runtime/common/xwalk_system_locale.h',
+ ],
+ },
+ {
'target_name': 'xwalk-pkg-helper',
'type': 'executable',
'product_name': 'xwalk-pkg-helper',
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_APPLICATION_TOOLS_LINUX_XWALK_TIZEN_USER_H_
-#define XWALK_APPLICATION_TOOLS_LINUX_XWALK_TIZEN_USER_H_
+#ifndef XWALK_APPLICATION_TOOLS_TIZEN_XWALK_TIZEN_USER_H_
+#define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_TIZEN_USER_H_
// When developing on Tizen, we log into the device using 'sdb' as the
// 'root' user, when changing to the 'app' user (the user as all Applications
int xwalk_tizen_check_user_app(void);
-#endif // XWALK_APPLICATION_TOOLS_LINUX_XWALK_TIZEN_USER_H_
+#endif // XWALK_APPLICATION_TOOLS_TIZEN_XWALK_TIZEN_USER_H_
#include "dbus/object_proxy.h"
#include "xwalk/application/common/application_storage.h"
-#include "xwalk/application/common/installer/package_installer.h"
#include "xwalk/application/tools/linux/dbus_connection.h"
+#include "xwalk/application/tools/tizen/xwalk_package_installer.h"
#include "xwalk/runtime/common/xwalk_paths.h"
-#if defined(OS_TIZEN)
#include "xwalk/application/common/id_util.h"
-#include "xwalk/application/tools/linux/xwalk_tizen_user.h"
-#endif
+#include "xwalk/application/tools/tizen/xwalk_tizen_user.h"
using xwalk::application::ApplicationData;
using xwalk::application::ApplicationStorage;
-using xwalk::application::PackageInstaller;
namespace {
char* install_path = NULL;
char* uninstall_id = NULL;
-#if defined(OS_TIZEN)
+char* reinstall_path = NULL;
char* operation_key = NULL;
int quiet = 0;
-#endif
gint debugging_port = -1;
gboolean continue_tasks = FALSE;
"Enable remote debugging, port number 0 means to disable", NULL },
{ "continue", 'c' , 0, G_OPTION_ARG_NONE, &continue_tasks,
"Continue the previous unfinished tasks.", NULL},
-#if defined(OS_TIZEN)
+ { "reinstall", 'r', 0, G_OPTION_ARG_STRING, &reinstall_path,
+ "Reinstall the application with path", "PATH" },
{ "key", 'k', 0, G_OPTION_ARG_STRING, &operation_key,
"Unique operation key", "KEY" },
{ "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
"Quiet mode", NULL },
-#endif
{ NULL }
};
g_type_init();
#endif
-#if defined(OS_TIZEN)
if (xwalk_tizen_check_user_app())
exit(1);
-#endif
context = g_option_context_new("- Crosswalk Application Management");
if (!context) {
scoped_ptr<PackageInstaller> installer =
PackageInstaller::Create(storage.get());
-#if defined(OS_TIZEN)
installer->SetQuiet(static_cast<bool>(quiet));
if (operation_key)
installer->SetInstallationKey(operation_key);
-#endif
if (continue_tasks) {
g_print("trying to continue previous unfinished tasks.\n");
}
} else if (uninstall_id) {
success = installer->Uninstall(uninstall_id);
+ } else if (reinstall_path) {
+ success = installer->Reinstall(base::FilePath(reinstall_path));
} else if (debugging_port >= 0) {
#if defined(SHARED_PROCESS_MODE)
// Deal with the case "xwalkctl -d PORT_NUMBER"
'sources': [
'browser/application_tizen.cc',
'browser/application_tizen.h',
+ 'browser/application_service_tizen.cc',
+ 'browser/application_service_tizen.h',
],
}],
],
'conditions': [
['OS=="linux"', {
'dependencies': [
- 'application/tools/linux/xwalk_application_tools.gyp:xwalkctl',
'application/tools/linux/xwalk_application_tools.gyp:xwalk_launcher',
],
}],
['tizen == 1', {
'dependencies': [
+ 'application/tools/tizen/xwalk_tizen_tools.gyp:xwalkctl',
'application/tools/tizen/xwalk_tizen_tools.gyp:xwalk-pkg-helper',
'application/tools/tizen/xwalk_tizen_tools.gyp:xwalk-backendlib',
],
(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, 'extension_manager.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),
(os.path.join(tools_src_dir, 'manifest_json_parser.py'), target_dir),
- (os.path.join(tools_src_dir, 'parse_xpk.py'), target_dir)
+ (os.path.join(tools_src_dir, 'parse_xpk.py'), target_dir),
+ (os.path.join(tools_src_dir, 'util.py'), target_dir)
]
for index in range(len(source_target_list)):
# 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.
-# pylint: disable=F0401
import optparse
import os
-import shutil
import sys
import zipfile
-LIBRARY_PROJECT_NAME = 'xwalk_core_library'
-AAR_LIBRARY_NAME = 'xwalk_core_library_aar'
-def AddGeneratorOptions(option_parser):
- option_parser.add_option('-s', dest='source',
- help='Source directory of project root.',
- type='string')
- option_parser.add_option('-t', dest='target',
- help='Product out target directory.',
- type='string')
-
-
-def CopyProjectFiles(out_dir):
- """cp out/Release/xwalk_core_library/AndroidManifest<file>
- out/Release/xwalk_core_library_aar/<file>
- """
-
- print 'Copying library project files...'
- files_to_copy = [
- # AndroidManifest.xml from template.
- 'AndroidManifest.xml',
- ]
- for f in files_to_copy:
- source_file = os.path.join(out_dir, LIBRARY_PROJECT_NAME, f)
- target_file = os.path.join(out_dir, AAR_LIBRARY_NAME, f)
- shutil.copy2(source_file, target_file)
-
-
-def CopyBinaries(out_dir):
- """cp out/Release/xwalk_core_library/libs/*
- out/Release/xwalk_core_library_aar/jni/
- """
-
- print 'Copying binaries...'
- # Copy jar files to classes.jar.
- libs_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs')
-
- source_file = os.path.join(libs_dir, 'xwalk_core_library_java.jar')
- target_file = os.path.join(out_dir, AAR_LIBRARY_NAME, 'classes.jar')
- shutil.copyfile(source_file, target_file)
-
- # Copy native libraries.
- source_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'libs')
- target_dir = os.path.join(out_dir, AAR_LIBRARY_NAME, 'jni')
- if not os.path.exists(target_dir):
- os.makedirs(target_dir)
-
- if os.path.exists(source_dir):
- for item in os.listdir(source_dir):
- sub_path = os.path.join(source_dir, item)
- target_dir = os.path.join(target_dir, item)
- if os.path.isdir(sub_path):
- shutil.copytree(sub_path, target_dir)
-
- # Copy R.txt.
- r_source_dir = os.path.join(out_dir, 'gen', 'xwalk_core_internal_java')
- r_source_file = os.path.join(r_source_dir, 'java_R', 'R.txt')
- r_target_file = os.path.join(out_dir, AAR_LIBRARY_NAME, 'R.txt')
- shutil.copyfile(r_source_file, r_target_file)
-
-
-def CopyResources(out_dir):
- print 'Copying resources...'
- source_dir = os.path.join(out_dir, LIBRARY_PROJECT_NAME, 'res')
- target_dir = os.path.join(out_dir, AAR_LIBRARY_NAME, 'res')
- shutil.copytree(source_dir, target_dir)
-
-
-def GenerateAAR(aar_path, aar_dir):
- zfile = zipfile.ZipFile(aar_path, 'w')
- abs_src = os.path.abspath(aar_dir)
- for dirname, _, files in os.walk(aar_dir):
- for filename in files:
- absname = os.path.abspath(os.path.join(dirname, filename))
- relativename = absname[len(abs_src) + 1:]
- zfile.write(absname, relativename)
- zfile.close()
- #delete the AAR dir.
- shutil.rmtree(aar_dir)
-
-
-def main(argv):
- print 'Generating XWalkCore AAR Library...'
+def main():
option_parser = optparse.OptionParser()
- AddGeneratorOptions(option_parser)
- options, _ = option_parser.parse_args(argv)
-
- if not os.path.exists(options.source):
- print 'Source project does not exist, please provide correct directory.'
- sys.exit(1)
- out_dir = options.target
-
- # Clean the aar library.
- aar_path = os.path.join(out_dir, 'xwalk_core_library.aar')
- if os.path.exists(aar_path):
- os.remove(aar_path)
-
- aar_dir = os.path.join(out_dir, AAR_LIBRARY_NAME)
- if os.path.exists(aar_dir):
- shutil.rmtree(aar_dir)
- os.mkdir(aar_dir)
-
- # Copy Eclipse project files of library project.
- CopyProjectFiles(out_dir)
- # Copy binaries and resuorces.
- CopyResources(out_dir)
- CopyBinaries(out_dir)
- GenerateAAR(aar_path, aar_dir)
+ option_parser.add_option('-t', dest='target',
+ help='Product out target directory.')
+ options, _ = option_parser.parse_args()
+
+ # The first entry of each tuple is the source file/directory that will be
+ # copied (and must exist), the second entry is its relative path inside the
+ # AAR file.
+ dirs = (
+ (os.path.join(options.target, 'xwalk_core_library', 'libs'),
+ 'jni'),
+ (os.path.join(options.target, 'xwalk_core_library', 'res'),
+ 'res'),
+ )
+ files = (
+ (os.path.join(options.target, 'gen', 'xwalk_core_internal_java', 'java_R',
+ 'R.txt'),
+ 'R.txt'),
+ (os.path.join(options.target, 'xwalk_core_library', 'AndroidManifest.xml'),
+ 'AndroidManifest.xml'),
+ (os.path.join(options.target, 'xwalk_core_library', 'libs',
+ 'xwalk_core_library_java.jar'),
+ 'classes.jar'),
+ )
+
+ aar_path = os.path.join(options.target, 'xwalk_core_library.aar')
+ with zipfile.ZipFile(aar_path, 'w') as aar_file:
+ for src, dest in files:
+ aar_file.write(src, dest)
+ for src, dest in dirs:
+ for root, _, files in os.walk(src):
+ for f in files:
+ real_path = os.path.join(root, f)
+ zip_path = os.path.join(dest, os.path.relpath(root, src), f)
+ aar_file.write(real_path, zip_path)
+
+ return 0
if __name__ == '__main__':
- sys.exit(main(sys.argv))
+ sys.exit(main())
'tizen%': 0,
'tizen_mobile%': 0,
'shared_process_mode%': 0,
+ 'enable_murphy%': 0,
},
'target_defaults': {
'variables': {
'tizen%': '<(tizen)',
'tizen_mobile%': '<(tizen_mobile)',
+ 'enable_murphy%': '<(enable_murphy)',
},
'conditions': [
['tizen==1', {
['shared_process_mode==1', {
'defines': ['SHARED_PROCESS_MODE=1'],
}],
+ ['enable_murphy==1', {
+ 'defines': ['ENABLE_MURPHY=1'],
+ }],
],
'includes': [
'xwalk_filename_rules.gypi',
extension.internal.sendSyncMessage("get");
}
+var getRealPath = function(virtual_root) {
+ var _msg = {
+ cmd : "getRealPath",
+ path : virtual_root
+ }
+ return extension.internal.sendSyncMessage(_msg);
+}
+
NativeFileSystem.prototype = new Object();
NativeFileSystem.prototype.constructor = NativeFileSystem;
NativeFileSystem.prototype.requestNativeFileSystem = requestNativeFileSystem;
NativeFileSystem.prototype.getDirectoryList = getDirectoryList;
+NativeFileSystem.prototype.getRealPath = getRealPath;
exports = new NativeFileSystem();
checker->DoTask();
}
+void NativeFileSystemInstance::HandleSyncMessage(
+ scoped_ptr<base::Value> msg) {
+ base::DictionaryValue* dict;
+ std::string command;
+
+ if (!msg->GetAsDictionary(&dict) || !dict->GetString("cmd", &command)) {
+ LOG(ERROR) << "Fail to handle command sync message.";
+ SendSyncReplyToJS(scoped_ptr<base::Value>(new base::StringValue("")));
+ return;
+ }
+
+ scoped_ptr<base::Value> result(new base::StringValue(""));
+ std::string virtual_root_string = "";
+ if ("getRealPath" == command &&
+ dict->GetString("path", &virtual_root_string)) {
+ std::transform(virtual_root_string.begin(),
+ virtual_root_string.end(),
+ virtual_root_string.begin(),
+ ::toupper);
+ std::string real_path =
+ VirtualRootProvider::GetInstance()->GetRealPath(
+ virtual_root_string);
+ result.reset(new base::StringValue(real_path));
+ } else {
+ LOG(ERROR) << command << " ASSERT NOT REACHED.";
+ }
+
+ SendSyncReplyToJS(result.Pass());
+}
+
FileSystemChecker::FileSystemChecker(
int process_id,
const std::string& path,
// XWalkExtensionInstance implementation.
virtual void HandleMessage(scoped_ptr<base::Value> msg) OVERRIDE;
+ virtual void HandleSyncMessage(scoped_ptr<base::Value> msg) OVERRIDE;
private:
XWalkExtensionFunctionHandler handler_;
+++ /dev/null
-Author: Sudarsana Nagineni <sudarsana.nagineni@intel.com>
-
-This patch includes Chromium side changes needed for integrating
-WebMediaPlayer with the Tizen Audio Session Manager.
-
-Also, it has changes that are needed for generating audio-session-manager
-stubs and load the library dynamically in the Browser process.
-
-audio-session-manager is using an _attribute_((constructor)) to initialize
-code and setup signal handlers at startup. So, linking with this library
-is causing a sandbox violation by executing the code in Renderer Process,
-since the Renderer Process and the Browser Process are linked with the
-same libraries.
-
-To prevent the problem, we load the audio-session-manager dynamically in
-the Browser process.
-
-diff --git src/build/linux/system.gyp src/build/linux/system.gyp
-index 4a7e857..f89d256 100644
---- src/build/linux/system.gyp
-+++ src/build/linux/system.gyp
-@@ -874,5 +874,19 @@
- }],
- ],
- },
-+ {
-+ 'target_name': 'audio_session_manager',
-+ 'type': 'none',
-+ 'toolsets': ['host', 'target'],
-+ 'conditions': [
-+ ['tizen_mobile == 1', {
-+ 'direct_dependent_settings': {
-+ 'cflags': [
-+ '<!@(<(pkg-config) --cflags audio-session-mgr)',
-+ ],
-+ },
-+ }],
-+ ],
-+ },
- ],
- }
-diff --git src/content/browser/renderer_host/render_view_host_impl.cc src/content/browser/renderer_host/render_view_host_impl.cc
-index 0912144..adf0a1b 100644
---- src/content/browser/renderer_host/render_view_host_impl.cc
-+++ src/content/browser/renderer_host/render_view_host_impl.cc
-@@ -89,4 +89,6 @@
- #include "content/browser/media/android/browser_media_player_manager.h"
-+#elif defined(OS_TIZEN_MOBILE)
-+#include "xwalk/tizen/browser/browser_mediaplayer_manager.h"
- #elif defined(OS_WIN)
- #include "base/win/win_util.h"
- #endif
-
- using base::TimeDelta;
-@@ -223,6 +225,8 @@ RenderViewHostImpl::RenderViewHostImpl(
-
- #if defined(OS_ANDROID)
- media_player_manager_.reset(BrowserMediaPlayerManager::Create(this));
-+#elif defined(OS_TIZEN_MOBILE)
-+ media_player_manager_.reset(tizen::BrowserMediaPlayerManager::Create(this));
- #endif
- }
-
-diff --git src/content/browser/renderer_host/render_view_host_impl.h src/content/browser/renderer_host/render_view_host_impl.h
-index d63bae3..d0602c7 100644
---- src/content/browser/renderer_host/render_view_host_impl.h
-+++ src/content/browser/renderer_host/render_view_host_impl.h
-@@ -42,6 +42,12 @@ struct ViewHostMsg_ShowPopup_Params;
- struct ViewMsg_Navigate_Params;
- struct ViewMsg_PostMessage_Params;
-
-+#if defined(OS_TIZEN_MOBILE)
-+namespace tizen {
-+class BrowserMediaPlayerManager;
-+}
-+#endif
-+
- namespace base {
- class ListValue;
- }
-@@ -704,6 +710,8 @@ class CONTENT_EXPORT RenderViewHostImpl
- #if defined(OS_ANDROID)
- // Manages all the android mediaplayer objects and handling IPCs for video.
- scoped_ptr<BrowserMediaPlayerManager> media_player_manager_;
-+#elif defined(OS_TIZEN_MOBILE)
-+ scoped_ptr<tizen::BrowserMediaPlayerManager> media_player_manager_;
- #endif
-
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
-diff --git src/content/common/content_message_generator.h src/content/common/content_message_generator.h
-index 78e7c53..a3cda01 100644
---- src/content/common/content_message_generator.h
-+++ src/content/common/content_message_generator.h
-@@ -57,3 +57,6 @@
- #include "content/common/view_messages.h"
- #include "content/common/websocket_messages.h"
- #include "content/common/worker_messages.h"
-+#if defined(OS_TIZEN_MOBILE)
-+#include "xwalk/tizen/common/media_player_messages.h"
-+#endif
-diff --git src/content/content_browser.gypi src/content/content_browser.gypi
-index 6570d15..d47cee2 100644
---- src/content/content_browser.gypi
-+++ src/content/content_browser.gypi
-@@ -1641,5 +1641,69 @@
- 'browser/geolocation/wifi_data_provider_linux.cc',
- ],
- }],
-+ ['tizen_mobile == 1', {
-+ 'sources': [
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager.cc',
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager.h',
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager_init.cc',
-+ '<(DEPTH)/xwalk/tizen/browser/audio_session_manager_init.h',
-+ '<(DEPTH)/xwalk/tizen/browser/browser_mediaplayer_manager.cc',
-+ '<(DEPTH)/xwalk/tizen/browser/browser_mediaplayer_manager.h',
-+ ],
-+ 'variables': {
-+ 'generate_stubs_script': '../tools/generate_stubs/generate_stubs.py',
-+ 'extra_header': '../xwalk/tizen/browser/audio_session_manager_stub_headers.fragment',
-+ 'sig_files': ['../xwalk/tizen/browser/audio_session_manager.sigs'],
-+ 'outfile_type': 'posix_stubs',
-+ 'stubs_filename_root': 'audio_session_manager_stubs',
-+ 'project_path': 'xwalk/tizen/browser',
-+ 'intermediate_dir': '<(INTERMEDIATE_DIR)',
-+ 'output_root': '<(SHARED_INTERMEDIATE_DIR)/audio_session_manager',
-+ },
-+ 'include_dirs': [
-+ '<(output_root)',
-+ ],
-+ 'actions': [
-+ {
-+ 'action_name': 'generate_stubs',
-+ 'inputs': [
-+ '<(generate_stubs_script)',
-+ '<(extra_header)',
-+ '<@(sig_files)',
-+ ],
-+ 'outputs': [
-+ '<(intermediate_dir)/<(stubs_filename_root).cc',
-+ '<(output_root)/<(project_path)/<(stubs_filename_root).h',
-+ ],
-+ 'action': ['python',
-+ '<(generate_stubs_script)',
-+ '-i', '<(intermediate_dir)',
-+ '-o', '<(output_root)/<(project_path)',
-+ '-t', '<(outfile_type)',
-+ '-e', '<(extra_header)',
-+ '-s', '<(stubs_filename_root)',
-+ '-p', '<(project_path)',
-+ '<@(_inputs)',
-+ ],
-+ 'process_outputs_as_sources': 1,
-+ 'message': 'Generating audio session manager stubs for dynamic loading',
-+ },
-+ ],
-+ 'conditions': [
-+ ['OS=="linux" or OS=="solaris"', {
-+ 'link_settings': {
-+ 'libraries': [
-+ '-ldl',
-+ ],
-+ },
-+ }],
-+ ],
-+ 'dependencies': [
-+ '../build/linux/system.gyp:audio_session_manager',
-+ ],
-+ 'export_dependent_settings': [
-+ '../build/linux/system.gyp:audio_session_manager',
-+ ],
-+ }],
- ],
- }
-diff --git src/content/content_common.gypi src/content/content_common.gypi
-index 1bfcccd..46db168 100644
---- src/content/content_common.gypi
-+++ src/content/content_common.gypi
-@@ -656,5 +656,10 @@
- }, {
- 'defines': ['USE_SECCOMP_BPF'],
- }],
-+ ['tizen_mobile == 1', {
-+ 'sources': [
-+ '<(DEPTH)/xwalk/tizen/common/media_player_messages.h',
-+ ],
-+ }],
- ['OS=="win" and directxsdk_exists=="True"', {
- 'actions': [
- {
-diff --git src/content/content_renderer.gypi src/content/content_renderer.gypi
-index 1e72a81..3bceb70 100644
---- src/content/content_renderer.gypi
-+++ src/content/content_renderer.gypi
-@@ -752,6 +752,14 @@
- }],
- ],
- }],
-+ ['tizen_mobile == 1', {
-+ 'sources': [
-+ '<(DEPTH)/xwalk/tizen/renderer/mediaplayer_impl.cc',
-+ '<(DEPTH)/xwalk/tizen/renderer/mediaplayer_impl.h',
-+ '<(DEPTH)/xwalk/tizen/renderer/renderer_mediaplayer_manager.cc',
-+ '<(DEPTH)/xwalk/tizen/renderer/renderer_mediaplayer_manager.h',
-+ ],
-+ }],
- ],
- 'target_conditions': [
- ['OS=="android"', {
-diff --git src/content/renderer/render_view_impl.cc src/content/renderer/render_view_impl.cc
-index c5a7059..cd42b4c 100644
---- src/content/renderer/render_view_impl.cc
-+++ src/content/renderer/render_view_impl.cc
-@@ -245,6 +245,11 @@
- #include "content/renderer/media/rtc_peer_connection_handler.h"
- #endif
-
-+#if defined(OS_TIZEN_MOBILE)
-+#include "xwalk/tizen/renderer/mediaplayer_impl.h"
-+#include "xwalk/tizen/renderer/renderer_mediaplayer_manager.h"
-+#endif
-+
- using blink::WebAXObject;
- using blink::WebApplicationCacheHost;
- using blink::WebApplicationCacheHostClient;
-@@ -844,6 +849,8 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
- body_background_color_(SK_ColorWHITE),
- expected_content_intent_id_(0),
- media_player_manager_(NULL),
-+#elif defined(OS_TIZEN_MOBILE)
-+ media_player_manager_(NULL),
- #endif
- #if defined(OS_WIN)
- focused_plugin_id_(-1),
-@@ -967,6 +974,8 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
- #if defined(OS_ANDROID)
- media_player_manager_ = new RendererMediaPlayerManager(this);
- new JavaBridgeDispatcher(this);
-+#elif defined(OS_TIZEN_MOBILE)
-+ media_player_manager_ = new tizen::RendererMediaPlayerManager(this);
- #endif
-
- // The next group of objects all implement RenderViewObserver, so are deleted
-@@ -3044,6 +3053,13 @@ blink::WebMediaPlayer* RenderViewImpl::CreateMediaPlayer(
- base::Unretained(GetContentClient()->renderer()),
- static_cast<RenderFrame*>(render_frame)),
- sink);
-+
-+#if defined(OS_TIZEN_MOBILE)
-+ tizen::MediaPlayerImpl* media_player = new tizen::MediaPlayerImpl(
-+ frame, client, AsWeakPtr(), media_player_manager_, params);
-+ return media_player;
-+#endif
-+
- return new WebMediaPlayerImpl(frame, client, AsWeakPtr(), params);
- #endif // defined(OS_ANDROID)
- }
-diff --git src/content/renderer/render_view_impl.h src/content/renderer/render_view_impl.h
-index ccfd1b5..8949cd0 100644
---- src/content/renderer/render_view_impl.h
-+++ src/content/renderer/render_view_impl.h
-@@ -128,6 +128,12 @@ namespace webkit_glue {
- class WebURLResponseExtraDataImpl;
- }
-
-+#if defined(OS_TIZEN_MOBILE)
-+namespace tizen {
-+class RendererMediaPlayerManager;
-+}
-+#endif
-+
- namespace content {
- class BrowserPluginManager;
- class DeviceOrientationDispatcher;
-@@ -1403,6 +1409,10 @@ class CONTENT_EXPORT RenderViewImpl
-
- // A date/time picker object for date and time related input elements.
- scoped_ptr<RendererDateTimePicker> date_time_picker_client_;
-+#elif defined(OS_TIZEN_MOBILE)
-+ // The media player manager for managing all the media players on this view
-+ // and for communicating with the audio session manager in browser process.
-+ tizen::RendererMediaPlayerManager* media_player_manager_;
- #endif
-
- // Plugins -------------------------------------------------------------------
%endif
Name: crosswalk
-Version: 9.38.198.0
+Version: 9.38.204.0
Release: 0
-Summary: Crosswalk is an app runtime based on Chromium
+Summary: Chromium-based app runtime
License: (BSD-3-Clause and LGPL-2.1+)
Group: Web Framework/Web Run Time
Url: https://github.com/otcshare/crosswalk
BuildRequires: pkgconfig(xtst)
%endif
+%if "%{profile}" == "ivi"
+BuildRequires: pkgconfig(murphy-common)
+BuildRequires: pkgconfig(murphy-resource)
+%endif
+
%if %{with wayland}
BuildRequires: pkgconfig(wayland-client)
BuildRequires: pkgconfig(wayland-cursor)
fi
%if %{with wayland}
-GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1 -Denable_xdg_shell=0"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1 -Denable_ozone_wayland_vkb=1 -Denable_xdg_shell=1"
%endif
GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Ddisable_nacl=%{_disable_nacl}"
export FFLAGS=`echo $FFLAGS | sed s,-mfpu=vfpv3,-mfpu=neon,g`
%endif
+%if "%{profile}" == "ivi"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Denable_murphy=1"
+%endif
+
# --no-parallel is added because chroot does not mount a /dev/shm, this will
# cause python multiprocessing.SemLock error.
export GYP_GENERATORS='ninja'
install -p -D src/out/Release/libffmpegsumo.so %{buildroot}%{_libdir}/xwalk/libffmpegsumo.so
install -p -D src/out/Release/xwalk.pak %{buildroot}%{_libdir}/xwalk/xwalk.pak
mkdir -p %{buildroot}%{_datadir}/xwalk
-install -p -D src/xwalk/application/common/installer/tizen/configuration/*.xsd %{buildroot}%{_datadir}/xwalk/
+install -p -D src/xwalk/application/common/tizen/configuration/*.xsd %{buildroot}%{_datadir}/xwalk/
# PNaCl
%if ! %{_disable_nacl}
[Service]
Type=dbus
BusName=org.crosswalkproject.Runtime1
+Environment=OZONE_WAYLAND_USE_XDG_SHELL='defined'
ExecStart=@LIB_INSTALL_DIR@/xwalk/xwalk --external-extensions-path=@LIB_INSTALL_DIR@/tizen-extensions-crosswalk
--- /dev/null
+// 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;
+
+public abstract class SharedXWalkExceptionHandler {
+ boolean handleException(Throwable e) {
+ onSharedLibraryNotFound();
+ return true;
+ }
+
+ public abstract void onSharedLibraryNotFound();
+}
--- /dev/null
+// 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.Activity;
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * The XWalkView that allows to use Crosswalk's shared library.
+ */
+public class SharedXWalkView extends XWalkView {
+ public SharedXWalkView(Context context, AttributeSet attrs,
+ SharedXWalkExceptionHandler handler) {
+ super(verifyActivity(context, handler), attrs);
+ }
+
+ public SharedXWalkView(Context context, Activity activity,
+ SharedXWalkExceptionHandler handler) {
+ super(context, verifyActivity(activity, handler));
+ }
+
+ private static Activity verifyActivity(Context context, SharedXWalkExceptionHandler handler) {
+ assert context instanceof Activity;
+ assert context.getApplicationContext() instanceof XWalkApplication;
+ ReflectionHelper.allowCrossPackage();
+ ReflectionHelper.setExceptionHandler(handler);
+ return (Activity) context;
+ }
+}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.app.runtime;
+package org.xwalk.core;
import android.app.Application;
+import android.content.Context;
import android.content.res.Resources;
/**
- * XWalkRuntimeApplication is to support cross package resource loading.
+ * XWalkApplication is to support cross package resource loading.
* It provides method to allow overriding getResources() behavior.
*/
-public class XWalkRuntimeApplication extends Application {
+public class XWalkApplication extends Application {
+ private static XWalkApplication gApp = null;
private Resources mRes = null;
@Override
+ public void onCreate(){
+ super.onCreate();
+ gApp = this;
+ }
+
+ @Override
public Resources getResources() {
return mRes == null ? super.getResources() : mRes;
}
if (mRes != null) return;
mRes = new XWalkMixedResources(super.getResources(), res);
}
+
+ static XWalkApplication getApplication() {
+ return gApp;
+ }
}
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.app.runtime;
+package org.xwalk.core;
import android.content.res.Resources;
import android.content.res.TypedArray;
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.runtime;
+package org.xwalk.core.internal;
import android.content.Context;
import android.content.ContextWrapper;
import java.util.Map;
import java.util.HashMap;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
/**
* This class is used to encapsulate the reflection invoking for bridge and wrapper.
*
private static Map<String, ConstructorHelper> sConstructorHelperMap =
new HashMap<String, ConstructorHelper>();
private static ClassLoader sBridgeOrWrapperLoader = null;
+ private static Context sBridgeContext = null;
private static boolean sIsWrapper;
private final static String INTERNAL_PACKAGE = "org.xwalk.core.internal";
+ private final static String LIBRARY_APK_PACKAGE = "org.xwalk.core";
+ /* Wrapper Only
+ private static boolean sAllowCrossPackage = false;
+ private static SharedXWalkExceptionHandler sExceptionHandler = null;
+
+ static void setExceptionHandler(SharedXWalkExceptionHandler handler) {
+ sExceptionHandler = handler;
+ }
+
+ public static boolean shouldUseLibrary() {
+ // TODO(wang16): There are many other conditions here.
+ // e.g. Whether application uses the ApplicationClass we provided,
+ // Whether native library arch is correct.
+ assert isWrapper();
+ try {
+ ReflectionHelper.class.getClassLoader().loadClass(
+ INTERNAL_PACKAGE + "." + "ReflectionHelper");
+ return false;
+ } catch (ClassNotFoundException e) {
+ return true;
+ }
+ }
+ Wrapper Only */
+
+ public static Context getBridgeContext() {
+ return sBridgeContext;
+ }
+
+ /* Wrapper Only
+ public static void allowCrossPackage() {
+ sAllowCrossPackage = true;
+ }
+ Wrapper Only */
- public static void init(boolean crossPackage) {
+ public static void init() {
assert isWrapper();
- if (!crossPackage) {
- initClassLoader(ReflectionHelper.class.getClassLoader());
+ /* Wrapper Only
+ if (shouldUseLibrary()) {
+ if (!sAllowCrossPackage) {
+ handleException("Use SharedXWalkView if you want to support shared mode");
+ }
+ XWalkApplication app = XWalkApplication.getApplication();
+ if (app == null) {
+ // TODO(wang16): Handle this well.
+ handleException("Shared mode requires XWalkApplication");
+ return;
+ }
+ try {
+ sBridgeContext = app.createPackageContext(
+ LIBRARY_APK_PACKAGE,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ } catch (PackageManager.NameNotFoundException e) {
+ handleException(e);
+ }
+ if (sBridgeContext != null) {
+ app.addResource(sBridgeContext.getResources());
+ initClassLoader(sBridgeContext.getClassLoader(), sBridgeContext);
+ }
} else {
- // TODO(wang16): Support shared mode and initClassLoader cross package.
+ initClassLoader(ReflectionHelper.class.getClassLoader(), null);
}
+ Wrapper Only */
}
- public static void initClassLoader(ClassLoader loader) {
+ public static void initClassLoader(ClassLoader loader, Context bridgeContext) {
sBridgeOrWrapperLoader = loader;
+ sBridgeContext = bridgeContext;
sBridgeWrapperMap.clear();
sConstructorMap.clear();
try {
// with wrapper's classloader via reflection.
Class<?> helperInBridge =
sBridgeOrWrapperLoader.loadClass(INTERNAL_PACKAGE + "." + "ReflectionHelper");
- Method initInBridge = helperInBridge.getMethod("initClassLoader", ClassLoader.class);
- initInBridge.invoke(null, ReflectionHelper.class.getClassLoader());
+ Method initInBridge = helperInBridge.getMethod(
+ "initClassLoader", ClassLoader.class, Context.class);
+ initInBridge.invoke(null, ReflectionHelper.class.getClassLoader(), sBridgeContext);
} else {
// JavascriptInterface is an annotation class bridge will use but declared in
// wrapper.
public static Class<?> loadClass(String clazz) {
// Any embedder using Embedding API should only use the exposed APIs which are
// in wrapper, so the initialization process is always starting from wrapper.
- if (sBridgeOrWrapperLoader == null) init(false);
+ if (sBridgeOrWrapperLoader == null) init();
+ if (sBridgeOrWrapperLoader == null) return null;
try {
return sBridgeOrWrapperLoader.loadClass(clazz);
} catch (ClassNotFoundException e) {
}
public static Method loadMethod(Class<?> clazz, String name, Object... paramTypes) {
+ if (sBridgeOrWrapperLoader == null) return null;
Class<?>[] params = new Class<?>[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
Object type = paramTypes[i];
public static void handleException(Exception e) {
e.printStackTrace();
+ /* Wrapper Only
+ if (isWrapper() && sExceptionHandler != null) {
+ if (sExceptionHandler.handleException(e)) return;
+ }
+ Wrapper Only */
throw new RuntimeException(e);
}
}
public static Object invokeMethod(Method m, Object instance, Object... parameters) {
+ if (sBridgeOrWrapperLoader == null) return null;
Object ret = null;
if (m != null) {
try {
// Convert between wrapper and bridge instance.
public static Object getBridgeOrWrapper(Object instance) {
+ if (sBridgeOrWrapperLoader == null) return null;
if (instance == null) return null;
Class<?> clazz = instance.getClass();
Method method = sBridgeWrapperMap.get(clazz);
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.xwalk.core.internal.extension;
+package org.xwalk.core.internal;
import android.os.Environment;
*/
static final String ENABLE_JAVASCRIPT = "enable-javascript";
+ /**
+ * The key string to enable/disable xwalk extensions.
+ *
+ */
+ static final String ENABLE_EXTENSIONS = "enable-extensions";
+
static {
sPrefMap.put(REMOTE_DEBUGGING, new PreferenceValue(false));
sPrefMap.put(ANIMATABLE_XWALK_VIEW, new PreferenceValue(false));
sPrefMap.put(
ALLOW_UNIVERSAL_ACCESS_FROM_FILE, new PreferenceValue(false));
sPrefMap.put(SUPPORT_MULTIPLE_WINDOWS, new PreferenceValue(true));
+ sPrefMap.put(ENABLE_EXTENSIONS, new PreferenceValue(true));
}
/**
import org.chromium.base.ApplicationStatus;
import org.chromium.base.ApplicationStatus.ActivityStateListener;
import org.chromium.base.CommandLine;
-
-import org.xwalk.core.internal.extension.XWalkExtensionManager;
-import org.xwalk.core.internal.extension.XWalkPathHelper;
+import org.xwalk.core.internal.extension.BuiltinXWalkExtensions;
/**
* <p>XWalkViewInternal represents an Android view for web apps/pages. Thus most of attributes
private XWalkContent mContent;
private Activity mActivity;
private Context mContext;
- private XWalkExtensionManager mExtensionManager;
private boolean mIsHidden;
private XWalkActivityStateListener mActivityStateListener;
@XWalkAPI(preWrapperLines = {
" super(${param1}, ${param2});"},
postWrapperLines = {
+ " if (bridge == null) return;",
" addView((FrameLayout)bridge, new FrameLayout.LayoutParams(",
" FrameLayout.LayoutParams.MATCH_PARENT,",
" FrameLayout.LayoutParams.MATCH_PARENT));"})
public XWalkViewInternal(Context context, AttributeSet attrs) {
- super(context, attrs);
+ super(convertContext(context), attrs);
checkThreadSafety();
- mContext = context;
- init(context, attrs);
+ mActivity = (Activity) context;
+ mContext = getContext();
+ init(mContext, attrs);
}
/**
@XWalkAPI(preWrapperLines = {
" super(${param1}, null);"},
postWrapperLines = {
+ " if (bridge == null) return;",
" addView((FrameLayout)bridge, new FrameLayout.LayoutParams(",
" FrameLayout.LayoutParams.MATCH_PARENT,",
" FrameLayout.LayoutParams.MATCH_PARENT));"})
public XWalkViewInternal(Context context, Activity activity) {
- super(context, null);
- checkThreadSafety();
+ super(convertContext(context), null);
+ checkThreadSafety();
// Make sure mActivity is initialized before calling 'init' method.
mActivity = activity;
- mContext = context;
- init(context, null);
+ mContext = getContext();
+ init(mContext, null);
+ }
+
+ private static Context convertContext(Context context) {
+ Context ret = context;
+ Context bridgeContext = ReflectionHelper.getBridgeContext();
+ if (bridgeContext == null || context == null ||
+ bridgeContext.getPackageName().equals(context.getPackageName())) {
+ // Not acrossing package
+ ret = context;
+ } else {
+ ret = new MixedContext(bridgeContext, context);
+ }
+ return ret;
}
/**
setNotificationService(new XWalkNotificationServiceImpl(context, this));
if (!CommandLine.getInstance().hasSwitch("disable-xwalk-extensions")) {
- // Enable xwalk extension mechanism and start load extensions here.
- // Note that it has to be after above initialization.
- mExtensionManager = new XWalkExtensionManager(context, getActivity());
- mExtensionManager.loadExtensions();
+ BuiltinXWalkExtensions.load(context, getActivity());
+ } else {
+ XWalkPreferencesInternal.setValue(XWalkPreferencesInternal.ENABLE_EXTENSIONS, false);
}
XWalkPathHelper.initialize();
@XWalkAPI
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mContent == null) return;
- if (null != mExtensionManager)
- mExtensionManager.onActivityResult(requestCode, resultCode, data);
mContent.onActivityResult(requestCode, resultCode, data);
}
if (mContent == null) return;
ApplicationStatus.unregisterActivityStateListener(mActivityStateListener);
mActivityStateListener = null;
- if (null != mExtensionManager) mExtensionManager.onDestroy();
mContent.destroy();
disableRemoteDebugging();
}
switch (newState) {
case ActivityState.STARTED:
onShow();
- if (null != mExtensionManager) mExtensionManager.onStart();
break;
case ActivityState.PAUSED:
pauseTimers();
- if (null != mExtensionManager) mExtensionManager.onPause();
break;
case ActivityState.RESUMED:
resumeTimers();
- if (null != mExtensionManager) mExtensionManager.onResume();
break;
case ActivityState.DESTROYED:
onDestroy();
break;
case ActivityState.STOPPED:
onHide();
- if (null != mExtensionManager) mExtensionManager.onStop();
break;
default:
break;
@Override
public void activateContents() {
- // TODO: implement.
+ if (mXWalkContentsClient != null) mXWalkContentsClient.onRequestFocus();
}
@Override
--- /dev/null
+// 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.internal.extension;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+
+import org.xwalk.core.internal.XWalkExtensionInternal;
+import org.xwalk.core.internal.extension.api.contacts.Contacts;
+import org.xwalk.core.internal.extension.api.device_capabilities.DeviceCapabilities;
+import org.xwalk.core.internal.extension.api.launchscreen.LaunchScreenExtension;
+import org.xwalk.core.internal.extension.api.messaging.Messaging;
+import org.xwalk.core.internal.extension.api.presentation.PresentationExtension;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.util.Log;
+
+public class BuiltinXWalkExtensions {
+ private static final String TAG = "BuiltinXWalkExtension";
+ private static HashMap<String, XWalkExtensionInternal> sBuiltinExtensions =
+ new HashMap<String, XWalkExtensionInternal>();
+
+ public static void load(Context context, Activity activity) {
+ // Create all built-in extension instances here.
+ {
+ String jsApiContent = "";
+ try {
+ jsApiContent = getExtensionJSFileContent(
+ context, PresentationExtension.JS_API_PATH, true);
+ sBuiltinExtensions.put(PresentationExtension.JS_API_PATH,
+ new PresentationExtension(jsApiContent, activity));
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to read JS API file: " + PresentationExtension.JS_API_PATH);
+ }
+ }
+
+ {
+ String jsApiContent = "";
+ try {
+ jsApiContent = getExtensionJSFileContent(
+ context, LaunchScreenExtension.JS_API_PATH, true);
+ sBuiltinExtensions.put(LaunchScreenExtension.JS_API_PATH,
+ new LaunchScreenExtension(jsApiContent, activity));
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to read JS API file: " + LaunchScreenExtension.JS_API_PATH);
+ }
+ }
+
+ {
+ String jsApiContent = "";
+ try {
+ jsApiContent = getExtensionJSFileContent(
+ context, Contacts.JS_API_PATH, true);
+ sBuiltinExtensions.put(Contacts.JS_API_PATH,
+ new Contacts(jsApiContent, activity));
+ } catch(IOException e) {
+ Log.w(TAG, "Failed to read JS API file: " + Contacts.JS_API_PATH);
+ }
+ }
+
+ {
+ String jsApiContent = "";
+ try {
+ jsApiContent = getExtensionJSFileContent(
+ context, DeviceCapabilities.JS_API_PATH, true);
+ sBuiltinExtensions.put(DeviceCapabilities.JS_API_PATH,
+ new DeviceCapabilities(jsApiContent, activity));
+ } catch(IOException e) {
+ Log.w(TAG, "Failed to read JS API file: " + DeviceCapabilities.JS_API_PATH);
+ }
+ }
+
+ {
+ String jsApiContent = "";
+ try {
+ jsApiContent = getExtensionJSFileContent(
+ context, Messaging.JS_API_PATH, true);
+ sBuiltinExtensions.put(Messaging.JS_API_PATH,
+ new Messaging(jsApiContent, activity));
+ } catch(IOException e) {
+ Log.w(TAG, "Failed to read JS API file: " + Messaging.JS_API_PATH);
+ }
+ }
+ }
+
+
+ private static String getExtensionJSFileContent(Context context, String fileName, boolean fromRaw)
+ throws IOException {
+ String result = "";
+ InputStream inputStream = null;
+ try {
+ if (fromRaw) {
+ // If fromRaw is true, Try to find js file in res/raw first.
+ // And then try to get it from assets if failed.
+ Resources resource = context.getResources();
+ String resName = (new File(fileName).getName().split("\\."))[0];
+ int resId = resource.getIdentifier(resName, "raw", context.getPackageName());
+ if (resId > 0) {
+ try {
+ inputStream = resource.openRawResource(resId);
+ } catch (NotFoundException e) {
+ Log.w(TAG, "Inputstream failed to open for R.raw." + resName +
+ ", try to find it in assets");
+ }
+ }
+ }
+ if (inputStream == null) {
+ AssetManager assetManager = context.getAssets();
+ 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;
+ }
+}
+++ /dev/null
-// 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.internal.extension;
-
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * The public base class of xwalk extensions. Each extension should inherit
- * this class and implement its interfaces. Note that it's for every extensions.
- * For internal extensions, each one should base on it directly. For external
- * extensions, there'll be a bridge class in the runtime client side.
- */
-public abstract class XWalkExtension {
- // The unique name for this extension.
- protected String mName;
-
- // The JavaScript code stub. Will be injected to JS engine.
- protected String mJsApi;
-
- // The entry points are used when extension needs to have objects outside
- // the namespace that is implicitly created using its name.
- protected String[] mEntryPoints;
-
- // The context used by extensions.
- protected XWalkExtensionContext mExtensionContext;
-
- /**
- * Constructor with the information of an extension.
- * @param name the extension name.
- * @param apiVersion the version of API.
- * @param jsApi the code stub of JavaScript for this extension.
- * @param context the extension context.
- */
- public XWalkExtension(String name, String jsApi, XWalkExtensionContext context) {
- mName = name;
- mJsApi = jsApi;
- mEntryPoints = null;
- mExtensionContext = context;
- mExtensionContext.registerExtension(this);
- }
-
- /**
- * Constructor with the information of an extension.
- * @param name the extension name.
- * @param apiVersion the version of API.
- * @param jsApi the code stub of JavaScript for this extension.
- * @param entryPoints the entry points of JavaScript for this extension.
- * @param context the extension context.
- */
- public XWalkExtension(String name, String jsApi, String[] entryPoints, XWalkExtensionContext context) {
- mName = name;
- mJsApi = jsApi;
- mEntryPoints = entryPoints;
- mExtensionContext = context;
- mExtensionContext.registerExtension(this);
- }
-
- /**
- * Get the unique name of extension.
- * @return the name of extension set from constructor.
- */
- public String getExtensionName() {
- return mName;
- }
-
- /**
- * Get the JavaScript code stub.
- * @return the JavaScript code stub.
- */
- public String getJsApi() {
- return mJsApi;
- }
-
- /**
- * Get the entry points of extension.
- * @return the entry points.
- */
- public String[] getEntryPoints() {
- return mEntryPoints;
- }
-
- /**
- * JavaScript calls into Java code. The message is handled by
- * the extension implementation. The inherited classes should
- * override and add its implementation.
- * @param instanceID the ID of extension instance where the message came from.
- * @param message the message from JavaScript code.
- */
- public abstract void onMessage(int instanceID, String message);
-
- /**
- * Synchronized JavaScript calls into Java code. Similar to
- * onMessage. The only difference is it's a synchronized
- * message.
- * @param instanceID the ID of extension instance where the message came from.
- * @param message the message from JavaScript code.
- */
- public String onSyncMessage(int instanceID, String message) {
- return null;
- }
-
- /**
- * Post messages to JavaScript via extension's context.
- * It's used by child classes to post message from Java side
- * to JavaScript side.
- * @param instanceID the ID of target extension instance.
- * @param message the message to be passed to Javascript.
- */
- public final void postMessage(int instanceID, String message) {
- mExtensionContext.postMessage(this, instanceID, message);
- }
-
- /**
- * Broadcast messages to JavaScript via extension's context.
- * It's used by child classes to broad message from Java side
- * to all JavaScript side instances of the extension.
- * @param message the message to be passed to Javascript.
- */
- public final void broadcastMessage(String message) {
- mExtensionContext.broadcastMessage(this, message);
- }
-
- /**
- * Called when this app is onStart.
- */
- public void onStart() {
- }
-
- /**
- * Called when this app is onResume.
- */
- public void onResume() {
- }
-
- /**
- * Called when this app is onPause.
- */
- public void onPause() {
- }
-
- /**
- * Called when this app is onStop.
- */
- public void onStop() {
- }
-
- /**
- * Called when this app is onDestroy.
- */
- public void onDestroy() {
- }
-
- /**
- * Tell extension that one activity exists so that it can know the result
- * of the exit code.
- */
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- }
-}
+++ /dev/null
-// 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.internal.extension;
-
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * The public base class of xwalk external extensions. It acts a bridge class from
- * runtime to runtime client. The objects of class 'XWalkExtensionClient' in runtime
- * client side will be passed into this class because we need to call its methods.
- */
-class XWalkExtensionClientImpl extends XWalkExtension {
-
- private static final String TAG = XWalkExtensionClientImpl.class.getName();
- private Object mExtensionClient;
- private Method mOnMessage;
- private Method mOnSyncMessage;
- private Method mOnStart;
- private Method mOnResume;
- private Method mOnPause;
- private Method mOnStop;
- private Method mOnDestroy;
- private Method mOnActivityResult;
-
- public XWalkExtensionClientImpl(String name, String jsApi,
- XWalkExtensionContextWrapper context, Object extensionClient) {
- super(name, jsApi, context);
-
- mExtensionClient = extensionClient;
- mOnMessage = lookupMethod("onMessage", int.class, String.class);
- mOnSyncMessage = lookupMethod("onSyncMessage", int.class, String.class);
- mOnStart = lookupMethod("onStart");
- mOnResume = lookupMethod("onResume");
- mOnPause = lookupMethod("onPause");
- mOnStop = lookupMethod("onStop");
- mOnDestroy = lookupMethod("onDestroy");
- mOnActivityResult = lookupMethod("onActivityResult", int.class, int.class, Intent.class);
- }
-
- @Override
- public void onMessage(int extensionInstanceID, String message) {
- invokeMethod(mOnMessage, mExtensionClient, extensionInstanceID, message);
- }
-
- @Override
- public String onSyncMessage(int extensionInstanceID, String message) {
- return (String) invokeMethod(mOnSyncMessage, mExtensionClient, extensionInstanceID, message);
- }
-
- @Override
- public void onStart() {
- invokeMethod(mOnStart, mExtensionClient);
- }
-
- @Override
- public void onResume() {
- invokeMethod(mOnResume, mExtensionClient);
- }
-
- @Override
- public void onPause() {
- invokeMethod(mOnPause, mExtensionClient);
- }
-
- @Override
- public void onStop() {
- invokeMethod(mOnStop, mExtensionClient);
- }
-
- @Override
- public void onDestroy() {
- invokeMethod(mOnDestroy, mExtensionClient);
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- invokeMethod(mOnActivityResult, mExtensionClient, requestCode, resultCode, data);
- }
-
- private Method lookupMethod(String method, Class<?>... parameters) {
- Class<?> clientClass = mExtensionClient.getClass();
- try {
- return clientClass.getMethod(method, parameters);
- } catch (NoSuchMethodException e) {
- handleException(e);
- }
- return null;
- }
-
- private static Object invokeMethod(Method method, Object instance, Object... parameters) {
- Object result = null;
- if (method != null) {
- try {
- result = method.invoke(instance, parameters);
- } catch (IllegalArgumentException e) {
- handleException(e);
- } catch (IllegalAccessException e) {
- handleException(e);
- } catch (InvocationTargetException e) {
- handleException(e);
- } catch (NullPointerException e) {
- handleException(e);
- }
- }
- return result;
- }
-
- private static void handleException(Exception e) {
- Log.e(TAG, "Error in calling methods of external extensions. " + e.toString());
- e.printStackTrace();
- }
-}
+++ /dev/null
-// 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.internal.extension;
-
-import android.app.Activity;
-import android.content.Context;
-
-/**
- * Interface for extension context
- *
- * It is responsible for maintaining all xwalk extensions and providing a way to
- * post message to JavaScript side for each xwalk extension.
- */
-public interface XWalkExtensionContext {
- /**
- * Register an xwalk extension into context.
- */
- public void registerExtension(XWalkExtension extension);
-
- /**
- * Unregister an xwalk extension with the given unique name from context.
- */
- public void unregisterExtension(String name);
-
- /**
- * Post a message to the given extension instance.
- *
- * @param extension The xwalk extension
- * @param instanceId The unique id to identify the extension instance as the
- * message destination.
- * @param message The message content to be posted.
- */
- public void postMessage(XWalkExtension extension, int instanceId, String message);
-
- /**
- * Broadcast a message to all extension instances.
- *
- * @param extension The xwalk extension
- * @param message The message content to be broadcasted.
- */
- public void broadcastMessage(XWalkExtension extension, String message);
-
- /**
- * Get current Android Context.
- * @return the current Android Context.
- */
- public Context getContext();
-
- /**
- * Get the current Android Activity.
- * @return the current Android Activity.
- */
- public Activity getActivity();
-}
+++ /dev/null
-// 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.internal.extension;
-
-import android.app.Activity;
-import android.content.Context;
-
-/**
- * This is a public class to provide context for extensions.
- * It'll be shared by all external extensions.
- */
-class XWalkExtensionContextWrapper implements XWalkExtensionContext {
- private XWalkExtensionContext mOriginContext;
-
- public XWalkExtensionContextWrapper(XWalkExtensionContext context) {
- mOriginContext = context;
- }
-
- public void registerExtension(XWalkExtension extension) {
- mOriginContext.registerExtension(extension);
- }
-
- public void unregisterExtension(String name) {
- mOriginContext.unregisterExtension(name);
- }
-
- public void postMessage(XWalkExtension extension, int instanceID, String message) {
- mOriginContext.postMessage(extension, instanceID, message);
- }
-
- public void broadcastMessage(XWalkExtension extension, String message) {
- mOriginContext.broadcastMessage(extension, message);
- }
-
- public Context getContext() {
- // This is very tricky because for external extensions, we should
- // use Activity which contains the context for runtime client side.
- // mOriginContext.getContext() returns the context of library package,
- // e.g., the package context of runtime side.
- return mOriginContext.getActivity();
- }
-
- public Activity getActivity() {
- return mOriginContext.getActivity();
- }
-}
--- /dev/null
+// 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.internal.extension;
+
+import java.lang.ref.WeakReference;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ApplicationStatus.ActivityStateListener;
+import org.xwalk.core.internal.XWalkExtensionInternal;
+import org.xwalk.core.internal.XWalkViewInternal;
+
+import android.app.Activity;
+import android.content.Context;
+
+/**
+ * Base class for internal extensions which cares about host activity's lifecycle.
+ */
+public abstract class XWalkExtensionWithActivityStateListener extends XWalkExtensionInternal {
+
+ private class XWalkActivityStateListener implements ActivityStateListener {
+ WeakReference<XWalkExtensionWithActivityStateListener> mExtensionRef;
+
+ XWalkActivityStateListener(XWalkExtensionWithActivityStateListener extension) {
+ mExtensionRef = new WeakReference<XWalkExtensionWithActivityStateListener>(extension);
+ }
+
+ @Override
+ public void onActivityStateChange(Activity activity, int newState) {
+ XWalkExtensionWithActivityStateListener extension = mExtensionRef.get();
+ if (extension == null) return;
+ extension.onActivityStateChange(activity, newState);
+ }
+ }
+
+ private XWalkActivityStateListener mActivityStateListener;
+
+ private void initActivityStateListener(Activity activity) {
+ mActivityStateListener = new XWalkActivityStateListener(this);
+ ApplicationStatus.registerStateListenerForActivity(mActivityStateListener, activity);
+ }
+
+ public abstract void onActivityStateChange(Activity activity, int newState);
+
+ public XWalkExtensionWithActivityStateListener(String name, String jsApi, Activity activity) {
+ super(name, jsApi);
+ initActivityStateListener(activity);
+ }
+
+ public XWalkExtensionWithActivityStateListener(
+ String name, String jsApi, String[] entryPoints, Activity activity) {
+ super(name, jsApi, entryPoints);
+ initActivityStateListener(activity);
+ }
+}
package org.xwalk.core.internal.extension.api.contacts;
+import android.app.Activity;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import java.util.ArrayList;
+import org.chromium.base.ActivityState;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import org.xwalk.core.internal.extension.XWalkExtension;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
+import org.xwalk.core.internal.extension.XWalkExtensionWithActivityStateListener;
-public class Contacts extends XWalkExtension {
+public class Contacts extends XWalkExtensionWithActivityStateListener {
public static final String JS_API_PATH = "jsapi/contacts_api.js";
private static final String TAG = "Contacts";
private final ContactEventListener mObserver;
private final ContentResolver mResolver;
- public Contacts(String jsApiContent, XWalkExtensionContext context) {
- super(NAME, jsApiContent, context);
- mResolver = context.getContext().getContentResolver();
+ public Contacts(String jsApiContent, Activity activity) {
+ super(NAME, jsApiContent, activity);
+ mResolver = activity.getContentResolver();
mObserver = new ContactEventListener(new Handler(), this, mResolver);
mResolver.registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, mObserver);
}
+
+ @Override
+ public String onSyncMessage(int instanceID, String message) {
+ return null;
+ }
+
@Override
public void onMessage(int instanceID, String message) {
if (message.isEmpty()) return;
}
}
- @Override
- public void onResume() {
- mObserver.onResume();
- mResolver.registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, mObserver);
- }
-
- @Override
- public void onPause() {
- mResolver.unregisterContentObserver(mObserver);
- }
-
- @Override
- public void onDestroy() {
- mResolver.unregisterContentObserver(mObserver);
- }
-
// Remove all contacts.
private void handleClear() {
Cursor c = null;
if (c != null) c.close();
}
}
+
+
+ @Override
+ public void onActivityStateChange(Activity activity, int newState) {
+ switch (newState) {
+ case ActivityState.RESUMED:
+ mObserver.onResume();
+ mResolver.registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, mObserver);
+ break;
+ case ActivityState.PAUSED:
+ case ActivityState.DESTROYED:
+ mResolver.unregisterContentObserver(mObserver);
+ break;
+ default:
+ break;
+ }
+ }
}
package org.xwalk.core.internal.extension.api.device_capabilities;
+import android.app.Activity;
+import android.content.Context;
+import android.provider.ContactsContract;
import android.util.Log;
-import org.xwalk.core.internal.extension.XWalkExtension;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
+import org.xwalk.core.internal.extension.XWalkExtensionWithActivityStateListener;
+import org.chromium.base.ActivityState;
import org.json.JSONException;
import org.json.JSONObject;
-public class DeviceCapabilities extends XWalkExtension {
+public class DeviceCapabilities extends XWalkExtensionWithActivityStateListener {
public static final String JS_API_PATH = "jsapi/device_capabilities_api.js";
private static final String TAG = "DeviceCapabilities";
private DeviceCapabilitiesMemory mMemory;
private DeviceCapabilitiesStorage mStorage;
- public DeviceCapabilities(String jsApiContent, XWalkExtensionContext context) {
- super(NAME, jsApiContent, context);
+ public DeviceCapabilities(String jsApiContent, Activity activity) {
+ super(NAME, jsApiContent, activity);
- mCPU = new DeviceCapabilitiesCPU(this, context);
- mCodecs = new DeviceCapabilitiesCodecs(this, context);
+ Context context = activity.getApplicationContext();
+
+ mCPU = new DeviceCapabilitiesCPU(this);
+ mCodecs = new DeviceCapabilitiesCodecs(this);
mDisplay = new DeviceCapabilitiesDisplay(this, context);
mMemory = new DeviceCapabilitiesMemory(this, context);
- mStorage = new DeviceCapabilitiesStorage(this, context);
+ mStorage = new DeviceCapabilitiesStorage(this, activity);
}
private void handleMessage(int instanceID, String message) {
}
@Override
- public void onResume() {
- mDisplay.onResume();
- mStorage.onResume();
- }
-
- @Override
- public void onPause() {
- mDisplay.onPause();
- mStorage.onPause();
+ public void onActivityStateChange(Activity activity, int newState) {
+ switch (newState) {
+ case ActivityState.RESUMED:
+ mDisplay.onResume();
+ mStorage.onResume();
+ break;
+ case ActivityState.PAUSED:
+ mDisplay.onPause();
+ mStorage.onPause();
+ break;
+ case ActivityState.DESTROYED:
+ mDisplay.onDestroy();
+ mStorage.onDestroy();
+ break;
+ default:
+ break;
+ }
}
@Override
- public void onDestroy() {
- mDisplay.onDestroy();
- mStorage.onDestroy();
+ public String onSyncMessage(int instanceID, String message) {
+ return null;
}
}
import org.json.JSONException;
import org.json.JSONObject;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
class DeviceCapabilitiesCPU {
private static final String SYSTEM_INFO_STAT_FILE = "/proc/stat";
private String mCPUArch = "Unknown";
private double mCPULoad = 0.0;
- public DeviceCapabilitiesCPU(DeviceCapabilities instance,
- XWalkExtensionContext context) {
+ public DeviceCapabilitiesCPU(DeviceCapabilities instance) {
mDeviceCapabilities = instance;
// Get arch and core number at constructor since they won't change time to time.
package org.xwalk.core.internal.extension.api.device_capabilities;
import org.json.JSONObject;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
class DeviceCapabilitiesCodecs {
private XWalkMediaCodec mediaCodec;
- public DeviceCapabilitiesCodecs(DeviceCapabilities instance,
- XWalkExtensionContext context) {
+ public DeviceCapabilitiesCodecs(DeviceCapabilities instance) {
mediaCodec = XWalkMediaCodec.Create(instance);
}
import org.json.JSONException;
import org.json.JSONObject;
import org.xwalk.core.internal.extension.api.XWalkDisplayManager;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
class DeviceCapabilitiesDisplay {
private static final String TAG = "DeviceCapabilitiesDisplay";
};
public DeviceCapabilitiesDisplay(DeviceCapabilities instance,
- XWalkExtensionContext context) {
+ Context context) {
mDeviceCapabilities = instance;
- mDisplayManager = XWalkDisplayManager.getInstance(context.getContext());
+ mDisplayManager = XWalkDisplayManager.getInstance(context);
// Fetch the original display list
initDisplayList();
import org.json.JSONException;
import org.json.JSONObject;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
class DeviceCapabilitiesMemory {
private static final String MEM_INFO_FILE = "/proc/meminfo";
private long mCapacity = 0;
public DeviceCapabilitiesMemory(DeviceCapabilities instance,
- XWalkExtensionContext context) {
+ Context context) {
mDeviceCapabilities = instance;
- mContext = context.getContext();
+ mContext = context;
}
public JSONObject getInfo() {
package org.xwalk.core.internal.extension.api.device_capabilities;
+import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.SparseArray;
import java.io.File;
+import java.lang.ref.WeakReference;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
class DeviceCapabilitiesStorage {
private static final String TAG = "DeviceCapabilitiesStorage";
private DeviceCapabilities mDeviceCapabilities;
- private XWalkExtensionContext mExtensionContext;
+ private WeakReference<Activity> mActivity;
private static int mStorageCount = 0;
// Holds all available storages.
};
public DeviceCapabilitiesStorage(DeviceCapabilities instance,
- XWalkExtensionContext context) {
+ Activity activity) {
mDeviceCapabilities = instance;
- mExtensionContext = context;
+ mActivity = new WeakReference<Activity>(activity);
registerIntentFilter();
}
mIsListening = true;
- mExtensionContext.getActivity().registerReceiver(mStorageListener, mIntentFilter);
+ Activity activity = mActivity.get();
+ if (activity != null) activity.registerReceiver(mStorageListener, mIntentFilter);
}
public void unregisterListener() {
}
mIsListening = false;
- mExtensionContext.getActivity().unregisterReceiver(mStorageListener);
+ Activity activity = mActivity.get();
+ if (activity != null) activity.unregisterReceiver(mStorageListener);
}
private void notifyAndSaveAttachedStorage() {
package org.xwalk.core.internal.extension.api.launchscreen;
+import android.content.Context;
import android.content.Intent;
import android.util.Log;
+import org.xwalk.core.internal.XWalkExtensionInternal;
import org.xwalk.core.internal.XWalkLaunchScreenManager;
-import org.xwalk.core.internal.extension.XWalkExtension;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
/**
* A XWalk extension for LaunchScreen API implementation on Android.
*/
-public class LaunchScreenExtension extends XWalkExtension {
+public class LaunchScreenExtension extends XWalkExtensionInternal {
public final static String JS_API_PATH = "jsapi/launch_screen_api.js";
private final static String NAME = "xwalk.launchscreen";
// Command messages:
private final static String CMD_HIDE_LAUNCH_SCREEN = "hideLaunchScreen";
- public LaunchScreenExtension(String jsApi, XWalkExtensionContext context) {
- super(NAME, jsApi, JS_ENTRY_POINTS, context);
+ private Context mContext;
+
+ public LaunchScreenExtension(String jsApi, Context context) {
+ super(NAME, jsApi, JS_ENTRY_POINTS);
+ mContext = context;
}
@Override
// Need to be well designed in the future.
String filterStr = XWalkLaunchScreenManager.getHideLaunchScreenFilterStr();
Intent intent = new Intent(filterStr);
- mExtensionContext.getActivity().sendBroadcast(intent);
+ mContext.sendBroadcast(intent);
+ }
+
+ @Override
+ public String onSyncMessage(int instanceID, String message) {
+ return null;
}
}
import java.util.HashMap;
import java.util.Map;
+import org.chromium.base.ActivityState;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xwalk.core.internal.extension.api.messaging.MessagingManager;
import org.xwalk.core.internal.extension.api.messaging.MessagingSmsManager;
-import org.xwalk.core.internal.extension.XWalkExtension;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
+import org.xwalk.core.internal.extension.XWalkExtensionWithActivityStateListener;
interface Command {
void runCommand(int instanceID, JSONObject jsonMsg);
}
-public class Messaging extends XWalkExtension {
+public class Messaging extends XWalkExtensionWithActivityStateListener {
public static final String JS_API_PATH = "jsapi/messaging_api.js";
private static final String NAME = "xwalk.experimental.messaging";
}
}
- public Messaging(String jsApiContent, XWalkExtensionContext context) {
- super(NAME, jsApiContent, context);
- mSmsManager = new MessagingSmsManager(mExtensionContext.getActivity(), this);
+ public Messaging(String jsApiContent, Activity activity) {
+ super(NAME, jsApiContent, activity);
+ mSmsManager = new MessagingSmsManager(activity, this);
+ mMessagingManager = new MessagingManager(activity, this);
mSmsManager.registerIntentFilters();
- //FIXME:(shawn) When onStart and OnStop are ready. This should be moved to onStart.
- mMessagingManager = new MessagingManager(mExtensionContext.getActivity(), this);
initMethodMap();
}
@Override
- public void onDestroy() {
- mSmsManager.unregisterIntentFilters();
- //FIXME:(shawn) When onStart and OnStop are ready. This should be moved to onStop.
- }
-
- @Override
public void onMessage(int instanceID, String message) {
Command command = sMethodMap.get(getCommandString(message));
}
return "";
}
+
+ @Override
+ public void onActivityStateChange(Activity activity, int newState) {
+ if (newState == ActivityState.STOPPED) mSmsManager.unregisterIntentFilters();
+ else if (newState == ActivityState.STARTED) mSmsManager.registerIntentFilters();
+ }
}
import android.net.Uri;
import android.util.Log;
+import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
private final static String EXTRA_MSGTO = "to";
private final static String EXTRA_MSGINSTANCEID = "instanceid";
private final static String DEFAULT_SERVICE_ID = "sim0";
- private final Activity mMainActivity;
+ private final WeakReference<Activity> mActivity;
private final Messaging mMessagingHandler;
private BroadcastReceiver mSmsSentReceiver, mSmsDeliveredReceiver,
mSmsReceiveReceiver, mSmsServiceReceiver;
}
MessagingSmsManager(Activity activity, Messaging messaging) {
- mMainActivity = activity;
+ mActivity = new WeakReference<Activity>(activity);
mMessagingHandler = messaging;
}
private boolean checkService(String serviceID) {
+ Activity activity = mActivity.get();
+ if (activity == null) return false;
TelephonyManager tm =
- (TelephonyManager)mMainActivity.getSystemService(Context.TELEPHONY_SERVICE);
+ (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
return (TelephonyManager.SIM_STATE_READY == tm.getSimState());
}
if (!checkService(DEFAULT_SERVICE_ID)) {
Log.e(TAG, "No Sim Card");
}
+ Activity activity = mActivity.get();
+ if (activity == null) return;
+
String asyncCallId = null;
JSONObject eventBody = null;
String phone = null;
String instanceIDString = Integer.toString(instanceID);
intentSmsSent.putExtra(EXTRA_MSGINSTANCEID, instanceIDString);
int promiseIdInt = Integer.valueOf(asyncCallId);
- PendingIntent piSent = PendingIntent.getBroadcast(mMainActivity,
+ PendingIntent piSent = PendingIntent.getBroadcast(activity,
promiseIdInt,
intentSmsSent,
PendingIntent.FLAG_ONE_SHOT);
intentSmsDelivered.putExtra(EXTRA_MSGID, asyncCallId);
intentSmsDelivered.putExtra(EXTRA_MSGTEXT, smsMessage);
intentSmsDelivered.putExtra(EXTRA_MSGINSTANCEID, instanceIDString);
- PendingIntent piDelivered = PendingIntent.getBroadcast(mMainActivity,
+ PendingIntent piDelivered = PendingIntent.getBroadcast(activity,
-promiseIdInt,
intentSmsDelivered,
PendingIntent.FLAG_ONE_SHOT);
}
public void onSmsClear(int instanceID, JSONObject jsonMsg) {
+ Activity activity = mActivity.get();
+ if (activity == null) return;
+
String asyncCallId = null, cmd = null;
JSONObject eventBody = null;
String serviceID = null;
return;
}
- ContentResolver cr = mMainActivity.getContentResolver();
+ ContentResolver cr = activity.getContentResolver();
cr.delete(Uri.parse("content://sms"), null, null);
JSONObject jsonMsgRet = null;
}
public void registerIntentFilters() {
+ Activity activity = mActivity.get();
+ if (activity == null) return;
+
mSmsReceiveReceiver = new MessagingReceiver(mMessagingHandler) {
@Override
public void onReceive(Context context, Intent intent) {
mSmsSentReceiver = new MessagingReceiver(mMessagingHandler) {
@Override
public void onReceive(Context content, Intent intent) {
+ Activity activity = mActivity.get();
+ if (activity == null) return;
+
boolean error = getResultCode() != Activity.RESULT_OK;
String asyncCallId = intent.getStringExtra(EXTRA_MSGID);
String smsMessage = intent.getStringExtra(EXTRA_MSGTEXT);
ContentValues values = new ContentValues();
values.put("address", to);
values.put("body", smsMessage);
- mMainActivity.getContentResolver().insert(Uri.parse("content://sms/sent"), values);
+ activity.getContentResolver().insert(Uri.parse("content://sms/sent"), values);
}
};
}
};
- mMainActivity.registerReceiver(
+ activity.registerReceiver(
mSmsReceiveReceiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));
- mMainActivity.registerReceiver(
+ activity.registerReceiver(
mSmsSentReceiver, new IntentFilter("SMS_SENT"));
- mMainActivity.registerReceiver(
+ activity.registerReceiver(
mSmsDeliveredReceiver,new IntentFilter("SMS_DELIVERED"));
- mMainActivity.registerReceiver(
+ activity.registerReceiver(
mSmsServiceReceiver,new IntentFilter("android.intent.action.SIM_STATE_CHANGED"));
}
public void unregisterIntentFilters() {
- mMainActivity.unregisterReceiver(mSmsReceiveReceiver);
- mMainActivity.unregisterReceiver(mSmsSentReceiver);
- mMainActivity.unregisterReceiver(mSmsDeliveredReceiver);
- mMainActivity.unregisterReceiver(mSmsServiceReceiver);
+ Activity activity = mActivity.get();
+ if (activity == null) return;
+
+ activity.unregisterReceiver(mSmsReceiveReceiver);
+ activity.unregisterReceiver(mSmsSentReceiver);
+ activity.unregisterReceiver(mSmsDeliveredReceiver);
+ activity.unregisterReceiver(mSmsServiceReceiver);
}
public String getServiceIds() {
package org.xwalk.core.internal.extension.api.presentation;
+import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
+import android.provider.ContactsContract;
import android.util.JsonReader;
import android.util.JsonWriter;
import android.util.Log;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
+import java.lang.ref.WeakReference;
import java.net.URI;
import java.net.URISyntaxException;
+import org.chromium.base.ActivityState;
import org.chromium.base.ThreadUtils;
import org.xwalk.core.internal.extension.api.XWalkDisplayManager;
-import org.xwalk.core.internal.extension.XWalkExtension;
-import org.xwalk.core.internal.extension.XWalkExtensionContext;
+import org.xwalk.core.internal.extension.XWalkExtensionWithActivityStateListener;
/**
* A XWalk extension for Presentation API implementation on Android.
*/
-public class PresentationExtension extends XWalkExtension {
+public class PresentationExtension extends XWalkExtensionWithActivityStateListener {
public final static String JS_API_PATH = "jsapi/presentation_api.js";
private final static String NAME = "navigator.presentation";
private XWalkPresentationContent mPresentationContent;
private XWalkPresentationContent.PresentationDelegate mPresentationDelegate;
private PresentationView mPresentationView;
+ private Context mContext;
+ private WeakReference<Activity> mActivity;
/**
* Listens for the secondary display arrival and removal.
}
};
- public PresentationExtension(String jsApi, XWalkExtensionContext context) {
- super(NAME, jsApi, context);
+ public PresentationExtension(String jsApi, Activity activity) {
+ super(NAME, jsApi, activity);
- mDisplayManager = XWalkDisplayManager.getInstance(context.getContext());
+ mContext = activity.getApplicationContext();
+ mActivity = new WeakReference<Activity>(activity);
+ mDisplayManager = XWalkDisplayManager.getInstance(activity.getApplicationContext());
Display[] displays = mDisplayManager.getPresentationDisplays();
mAvailableDisplayCount = displays.length;
}
}
mPresentationContent = new XWalkPresentationContent(
- mExtensionContext.getContext(),
- mExtensionContext.getActivity(),
+ mContext,
+ mActivity,
new XWalkPresentationContent.PresentationDelegate() {
@Override
public void onContentLoaded(XWalkPresentationContent content) {
}
}
- @Override
public void onResume() {
Display[] displays = mDisplayManager.getPresentationDisplays();
ViewGroup parent = (ViewGroup)mPresentationContent.getContentView().getParent();
if (parent != null) parent.removeView(mPresentationContent.getContentView());
- mPresentationView = PresentationView.createInstance(mExtensionContext.getContext(), preferredDisplay);
+ mPresentationView = PresentationView.createInstance(mContext, preferredDisplay);
mPresentationView.setContentView(mPresentationContent.getContentView());
mPresentationView.setPresentationListener(new PresentationView.PresentationListener() {
@Override
mPresentationView.show();
}
- @Override
- public void onPause() {
- dismissPresentationView();
-
- if (mPresentationContent != null) mPresentationContent.onPause();
-
- // No need to listen display changes when the activity is paused.
- mDisplayManager.unregisterDisplayListener(mDisplayListener);
- }
-
- @Override
- public void onDestroy() {
- // close the presentation content if have.
- closePresentationContent();
- }
-
private void dismissPresentationView() {
if (mPresentationView == null) return;
mPresentationContent.close();
mPresentationContent = null;
}
+
+ @Override
+ public void onActivityStateChange(Activity activity, int newState) {
+ switch (newState) {
+ case ActivityState.RESUMED:
+ onResume();
+ break;
+ case ActivityState.PAUSED:
+ dismissPresentationView();
+ if (mPresentationContent != null) mPresentationContent.onPause();
+ // No need to listen display changes when the activity is paused.
+ mDisplayManager.unregisterDisplayListener(mDisplayListener);
+ break;
+ case ActivityState.DESTROYED:
+ // close the presentation content if have.
+ closePresentationContent();
+ break;
+ default:
+ break;
+ }
+ }
}
package org.xwalk.core.internal.extension.api.presentation;
+import java.lang.ref.WeakReference;
+
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
private int mPresentationId = INVALID_PRESENTATION_ID;
private XWalkViewInternal mContentView;
private Context mContext;
- private Activity mActivity;
+ private WeakReference<Activity> mActivity;
private PresentationDelegate mDelegate;
- public XWalkPresentationContent(Context context, Activity activity, PresentationDelegate delegate) {
+ public XWalkPresentationContent(
+ Context context, WeakReference<Activity> activity, PresentationDelegate delegate) {
mContext = context;
mActivity = activity;
mDelegate = delegate;
}
public void load(final String url) {
+ Activity activity = mActivity.get();
+ if (activity == null) return;
+
if (mContentView == null) {
- mContentView = new XWalkViewInternal(mContext, mActivity);
+ mContentView = new XWalkViewInternal(mContext, activity);
final XWalkUIClientInternal xWalkUIClient = new XWalkUIClientInternal(mContentView) {
@Override
public void onJavascriptCloseWindow(XWalkViewInternal view) {
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2012 The Chromium Authors. All rights reserved.
-
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
--->
-
-<!-- DO NOT ADD STRINGS HERE.
-
- Android content strings now live in
- xwalk/runtime/android/java/strings/android_xwalk_strings.grd
-
- See http://www.chromium.org/developers/design-documents/ui-localization
--->
-
-<resources/>
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.xwalk.runtime.lib">
+ package="org.xwalk.core">
- <application android:name="org.xwalk.runtime.lib.RuntimeLibApplication"
- android:label="XWalkRuntimeLib" android:hardwareAccelerated="true" android:icon="@drawable/crosswalk">
+ <application
+ android:label="XWalkCoreLibrary" android:hardwareAccelerated="true" android:icon="@drawable/crosswalk">
</application>
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
--- /dev/null
+# Source folder for xwalk_runtime_lib_apk
+## Why it's empty
+The "xwalk_runtime_lib_apk" is an apk target which
+provide xwalk_core_internal_java as library. The purpose
+of it is to be shared for other xwalk core embedders.
+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.
+
+++ /dev/null
-// 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.lib;
-
-import android.app.Application;
-
-public class RuntimeLibApplication extends Application {
-
- @Override
- public void onCreate() {
- super.onCreate();
- }
-}
-
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.xwalk.runtime.shell">
-
- <application android:name="android.app.Application"
- android:label="XWalkRuntimeShell" android:hardwareAccelerated="true">
- <activity android:name="org.xwalk.runtime.shell.XWalkRuntimeShellActivity"
- android:theme="@android:style/Theme.Holo.Light.NoActionBar"
- android:configChanges="orientation|keyboardHidden|keyboard|screenSize"
- android:label="XWalkRuntimeShell">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity android:name="org.xwalk.runtime.test.XWalkRuntimeTestRunnerActivity"
- android:label="XWalkRuntimeTestRunnerActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
- <provider android:name="org.xwalk.core.xwview.test.TestContentProvider"
- android:authorities="org.xwalk.core.xwview.test.TestContentProvider" />
- </application>
-
- <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.READ_CONTACTS"/>
- <uses-permission android:name="android.permission.READ_SMS" />
- <uses-permission android:name="android.permission.RECEIVE_SMS" />
- <uses-permission android:name="android.permission.RECORD_AUDIO"/>
- <uses-permission android:name="android.permission.SEND_SMS" />
- <uses-permission android:name="android.permission.WAKE_LOCK"/>
- <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.WRITE_SMS" />
-</manifest>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- 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.
- -->
-
-<LinearLayout android:id="@+id/testshell_activity"
- 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">
- <EditText android:id="@+id/url"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:gravity="bottom"
- android:textSize="18sp"
- android:autoText="true"
- android:capitalize="sentences"
- android:singleLine="true"
- android:selectAllOnFocus="true"
- android:inputType="textUri"
- android:imeOptions="actionGo" />
- </LinearLayout>
-
- <org.xwalk.runtime.XWalkRuntimeView android:id="@+id/content_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- </org.xwalk.runtime.XWalkRuntimeView>
-
-</LinearLayout>
-
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-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.
--->
-
-<resources>
- <string name="test_string">Hello, Crosswalk!</string>
-</resources>
+++ /dev/null
-// 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.shell;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.Context;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.View.OnFocusChangeListener;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
-
-import org.chromium.base.CommandLine;
-import org.chromium.base.BaseSwitches;
-import org.xwalk.runtime.XWalkRuntimeView;
-
-public class XWalkRuntimeShellActivity extends Activity {
- // TODO(yongsheng): Add one flag to hide the url bar.
- public static final String COMMAND_LINE_FILE = "/data/local/tmp/runtime-shell-command-line";
- private static final String TAG = XWalkRuntimeShellActivity.class.getName();
- public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs";
-
- private EditText mUrlTextView;
- private XWalkRuntimeView mRuntimeView;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (!CommandLine.isInitialized()) {
- CommandLine.initFromFile(COMMAND_LINE_FILE);
- String[] commandLineParams = getCommandLineParamsFromIntent(getIntent());
- if (commandLineParams != null) {
- CommandLine.getInstance().appendSwitchesAndArguments(commandLineParams);
- }
- }
-
- waitForDebuggerIfNeeded();
-
- setContentView(R.layout.testshell_activity);
- mRuntimeView = (XWalkRuntimeView) findViewById(R.id.content_container);
-
- initializeUrlField();
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- mRuntimeView.onStart();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mRuntimeView.onPause();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mRuntimeView.onResume();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- mRuntimeView.onStop();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mRuntimeView.onDestroy();
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- mRuntimeView.onActivityResult(requestCode, resultCode, data);
- }
-
- private void waitForDebuggerIfNeeded() {
- if (CommandLine.getInstance().hasSwitch(BaseSwitches.WAIT_FOR_JAVA_DEBUGGER)) {
- Log.e(TAG, "Waiting for Java debugger to connect...");
- android.os.Debug.waitForDebugger();
- Log.e(TAG, "Java debugger connected. Resuming execution.");
- }
- }
-
- private static String[] getCommandLineParamsFromIntent(Intent intent) {
- return intent != null ? intent.getStringArrayExtra(COMMAND_LINE_ARGS_KEY) : null;
- }
-
- private static String sanitizeUrl(String url) {
- if (url == null) return url;
- if (url.startsWith("www.") || url.indexOf(":") == -1) url = "http://" + url;
- return url;
- }
-
- private void initializeUrlField() {
- mUrlTextView = (EditText) findViewById(R.id.url);
- mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if ((actionId != EditorInfo.IME_ACTION_GO) && (event == null ||
- event.getKeyCode() != KeyEvent.KEYCODE_ENTER ||
- event.getAction() != KeyEvent.ACTION_DOWN)) {
- return false;
- }
-
- mRuntimeView.loadAppFromUrl(sanitizeUrl(mUrlTextView.getText().toString()));
- mUrlTextView.clearFocus();
- setKeyboardVisibilityForUrl(false);
- return true;
- }
- });
- mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- setKeyboardVisibilityForUrl(hasFocus);
- if (!hasFocus) {
- // TODO(yongsheng): Fix this.
- // mUrlTextView.setText(mRuntimeView.getUrl());
- }
- }
- });
- }
-
- private void setKeyboardVisibilityForUrl(boolean visible) {
- InputMethodManager imm = (InputMethodManager) getSystemService(
- Context.INPUT_METHOD_SERVICE);
- if (visible) {
- imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT);
- } else {
- imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0);
- }
- }
-}
+++ /dev/null
-// 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.
-
-/**
- * Content provider for testing content URLs.
- */
-
-package org.xwalk.runtime.test;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.database.AbstractCursor;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-// Note: if you move this class, make sure you have also updated AndroidManifest.xml
-public class TestContentProvider extends ContentProvider {
- private static final String AUTHORITY =
- "org.xwalk.runtime.test.TestContentProvider";
- private static final String CONTENT_SCHEME = "content://";
- private static final String CONTENT_TYPE = "image/png";
- private static final String GET_RESOURCE_REQUEST_COUNT = "get_resource_request_count";
- private static final String RESET_RESOURCE_REQUEST_COUNT = "reset_resource_request_count";
- private static final String TAG = "TestContentProvider";
- private enum ColumnIndex {
- RESOURCE_REQUEST_COUNT_COLUMN,
- };
- private final Map<String, Integer> mResourceRequestCount;
-
- public static String createContentUrl(String target) {
- return CONTENT_SCHEME + AUTHORITY + "/" + target;
- }
-
- private static Uri createRequestUri(final String target, String resource) {
- return Uri.parse(createContentUrl(target) + "?" + resource);
- }
-
- public static int getResourceRequestCount(Context context, String resource) {
- Uri uri = createRequestUri(GET_RESOURCE_REQUEST_COUNT, resource);
- final Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
- try {
- cursor.moveToFirst();
- return cursor.getInt(ColumnIndex.RESOURCE_REQUEST_COUNT_COLUMN.ordinal());
- } finally {
- cursor.close();
- }
- }
-
- public static void resetResourceRequestCount(Context context, String resource) {
- Uri uri = createRequestUri(RESET_RESOURCE_REQUEST_COUNT, resource);
- // A null cursor is returned for this request.
- context.getContentResolver().query(uri, null, null, null, null);
- }
-
- public TestContentProvider() {
- super();
- mResourceRequestCount = new HashMap<String, Integer>();
- }
-
- @Override
- public boolean onCreate() {
- return true;
- }
-
- @Override
- public AssetFileDescriptor openAssetFile(Uri uri, String mode) {
- String resource = uri.getLastPathSegment();
- if (mResourceRequestCount.containsKey(resource)) {
- mResourceRequestCount.put(resource, mResourceRequestCount.get(resource) + 1);
- } else {
- mResourceRequestCount.put(resource, 1);
- }
- return createImage();
- }
-
- @Override
- public String getType(Uri uri) {
- return CONTENT_TYPE;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String where,
- String[] whereArgs) {
- return 0;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- return 0;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- return null;
- }
-
- /**
- * Cursor object for retrieving resource request counters.
- */
- private static class ProviderStateCursor extends AbstractCursor {
- private final int mResourceRequestCount;
-
- public ProviderStateCursor(int resourceRequestCount) {
- mResourceRequestCount = resourceRequestCount;
- }
-
- @Override
- public boolean isNull(int columnIndex) {
- return columnIndex != ColumnIndex.RESOURCE_REQUEST_COUNT_COLUMN.ordinal();
- }
-
- @Override
- public int getCount() {
- return 1;
- }
-
- @Override
- public int getType(int columnIndex) {
- if (columnIndex == ColumnIndex.RESOURCE_REQUEST_COUNT_COLUMN.ordinal()) {
- return Cursor.FIELD_TYPE_INTEGER;
- }
- return Cursor.FIELD_TYPE_NULL;
- }
-
- private void unsupported() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public double getDouble(int columnIndex) {
- unsupported();
- return 0.0;
- }
-
- @Override
- public float getFloat(int columnIndex) {
- unsupported();
- return 0.0f;
- }
-
- @Override
- public int getInt(int columnIndex) {
- if (columnIndex == ColumnIndex.RESOURCE_REQUEST_COUNT_COLUMN.ordinal()) {
- return mResourceRequestCount;
- }
- return -1;
- }
-
- @Override
- public short getShort(int columnIndex) {
- unsupported();
- return 0;
- }
-
- @Override
- public long getLong(int columnIndex) {
- return getInt(columnIndex);
- }
-
- @Override
- public String getString(int columnIndex) {
- unsupported();
- return null;
- }
-
- @Override
- public String[] getColumnNames() {
- return new String[] { GET_RESOURCE_REQUEST_COUNT };
- }
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- String action = uri.getLastPathSegment();
- String resource = uri.getQuery();
- if (GET_RESOURCE_REQUEST_COUNT.equals(action)) {
- return new ProviderStateCursor(
- mResourceRequestCount.containsKey(resource) ?
- mResourceRequestCount.get(resource) : 0);
- } else if (RESET_RESOURCE_REQUEST_COUNT.equals(action)) {
- mResourceRequestCount.put(resource, 0);
- }
- return null;
- }
-
- // 1x1 black dot png image.
- private static final byte[] IMAGE = {
- (byte)0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00,
- 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x7e, (byte)0x9b, 0x55, 0x00,
- 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, (byte)0xae, (byte)0xce,
- 0x1c, (byte)0xe9, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x44, 0x41, 0x54, 0x08,
- 0x1d, 0x01, 0x02, 0x00, (byte)0xfd, (byte)0xff, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x01, (byte)0xcd, (byte)0xe3, (byte)0xd1, 0x2b, 0x00, 0x00, 0x00,
- 0x00, 0x49, 0x45, 0x4e, 0x44, (byte)0xae, 0x42, 0x60, (byte)0x82
- };
-
- private static AssetFileDescriptor createImage() {
- ParcelFileDescriptor[] pfds = null;
- FileOutputStream fileOut = null;
- try {
- try {
- pfds = ParcelFileDescriptor.createPipe();
- fileOut = new FileOutputStream(pfds[1].getFileDescriptor());
- fileOut.write(IMAGE);
- fileOut.flush();
- return new AssetFileDescriptor(pfds[0], 0, -1);
- } finally {
- if (fileOut != null) fileOut.close();
- if (pfds != null && pfds[1] != null) pfds[1].close();
- }
- } catch (IOException e) {
- Log.e(TAG, e.getMessage(), e);
- }
- return null;
- }
-}
+++ /dev/null
-// 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.runtime.test;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.widget.LinearLayout;
-
-/*
- * This is a lightweight activity for tests that only require XWalk functionality.
- */
-public class XWalkRuntimeTestRunnerActivity extends Activity {
-
- private LinearLayout mLinearLayout;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- boolean hardwareAccelerated = true;
-
- if (hardwareAccelerated) {
- getWindow().setFlags(
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- }
-
- mLinearLayout = new LinearLayout(this);
- mLinearLayout.setOrientation(LinearLayout.VERTICAL);
- mLinearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
- mLinearLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT));
-
- setContentView(mLinearLayout);
- }
-
- /**
- * Adds a view to the main linear layout.
- */
- public void addView(View view) {
- view.setLayoutParams(new LinearLayout.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1f));
- mLinearLayout.addView(view);
- }
-
- /**
- * Clears the main linear layout.
- */
- public void removeAllViews() {
- mLinearLayout.removeAllViews();
- }
-}
manifest_dictionary_ptr(manifest_dictionary);
xwalk::application::Manifest manifest(
- xwalk::application::Manifest::INVALID_TYPE,
manifest_dictionary_ptr.Pass());
std::string url;
// Enable Accelerated 2D Canvas.
command_line->AppendSwitch(switches::kGpuNoContextLost);
- const char* gl_name;
- if (base::PathExists(base::FilePath("/usr/lib/libGL.so")))
- gl_name = gfx::kGLImplementationDesktopName;
- else
- gl_name = gfx::kGLImplementationEGLName;
- command_line->AppendSwitchASCII(switches::kUseGL, gl_name);
+ if (!command_line->HasSwitch(switches::kUseGL)) {
+ const char* gl_name;
+ if (base::PathExists(base::FilePath("/usr/lib/libGL.so")))
+ gl_name = gfx::kGLImplementationDesktopName;
+ else
+ gl_name = gfx::kGLImplementationEGLName;
+ command_line->AppendSwitchASCII(switches::kUseGL, gl_name);
+ }
XWalkBrowserMainParts::PreMainMessageLoopStart();
}
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
#include "content/public/common/pepper_plugin_info.h"
+#if !defined(DISABLE_NACL)
+#include "ppapi/native_client/src/trusted/plugin/ppapi_entrypoints.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
+#endif
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "xwalk/application/common/constants.h"
namespace {
+#if !defined(DISABLE_NACL)
const char kNaClPluginMimeType[] = "application/x-nacl";
const char kNaClPluginExtension[] = "";
const char kNaClPluginDescription[] = "Native Client Executable";
const char kPnaclPluginMimeType[] = "application/x-pnacl";
const char kPnaclPluginExtension[] = "";
const char kPnaclPluginDescription[] = "Portable Native Client Executable";
+#endif
} // namespace
void XWalkContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {
+#if !defined(DISABLE_NACL)
// Handle Native Client just like the PDF plugin. This means that it is
// enabled by default for the non-portable case. This allows apps installed
// from the Chrome Web Store to use NaCl even if the command line switch
// isn't set. For other uses of NaCl we check for the command line switch.
// Specifically, Portable Native Client is only enabled by the command line
// switch.
- static bool skip_nacl_file_check = false;
base::FilePath path;
if (PathService::Get(xwalk::FILE_NACL_PLUGIN, &path)) {
- if (skip_nacl_file_check || base::PathExists(path)) {
- content::PepperPluginInfo nacl;
- nacl.path = path;
- nacl.name = XWalkContentClient::kNaClPluginName;
- content::WebPluginMimeType nacl_mime_type(kNaClPluginMimeType,
- kNaClPluginExtension,
- kNaClPluginDescription);
- nacl.mime_types.push_back(nacl_mime_type);
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisablePnacl)) {
- content::WebPluginMimeType pnacl_mime_type(kPnaclPluginMimeType,
- kPnaclPluginExtension,
- kPnaclPluginDescription);
- nacl.mime_types.push_back(pnacl_mime_type);
- }
- nacl.permissions = kNaClPluginPermissions;
- plugins->push_back(nacl);
-
- skip_nacl_file_check = true;
+ content::PepperPluginInfo nacl;
+ // The nacl plugin is now built into the Chromium binary.
+ nacl.is_internal = true;
+ nacl.path = path;
+ nacl.name = XWalkContentClient::kNaClPluginName;
+ content::WebPluginMimeType nacl_mime_type(kNaClPluginMimeType,
+ kNaClPluginExtension,
+ kNaClPluginDescription);
+ nacl.mime_types.push_back(nacl_mime_type);
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisablePnacl)) {
+ content::WebPluginMimeType pnacl_mime_type(kPnaclPluginMimeType,
+ kPnaclPluginExtension,
+ kPnaclPluginDescription);
+ nacl.mime_types.push_back(pnacl_mime_type);
}
+ nacl.internal_entry_points.get_interface = nacl_plugin::PPP_GetInterface;
+ nacl.internal_entry_points.initialize_module =
+ nacl_plugin::PPP_InitializeModule;
+ nacl.internal_entry_points.shutdown_module =
+ nacl_plugin::PPP_ShutdownModule;
+ nacl.permissions = kNaClPluginPermissions;
+ plugins->push_back(nacl);
}
+#endif
}
std::string XWalkContentClient::GetProduct() const {
return false;
cur = cur.Append(FILE_PATH_LITERAL("Widget Storage"));
break;
+ case xwalk::DIR_APPLICATION_PATH:
+ if (!GetXWalkDataPath(&cur))
+ return false;
+ cur = cur.Append(FILE_PATH_LITERAL("applications"));
+ break;
default:
return false;
}
// (subdir of DIR_PNACL_BASE).
DIR_TEST_DATA, // Directory where unit test data resides.
DIR_WGT_STORAGE_PATH, // Directory where widget storage data resides.
+ DIR_APPLICATION_PATH, // Directory where applications data is stored.
PATH_END
};
@Override
public void run() {
try {
- clickOnElementId("enter_fullscreen");
+ clickOnElementId("enter_fullscreen", null);
assertTrue(getXWalkView().hasEnteredFullscreen());
getXWalkView().leaveFullscreen();
assertFalse(getXWalkView().hasEnteredFullscreen());
- clickOnElementId("enter_fullscreen");
- clickOnElementId("exit_fullscreen");
+ clickOnElementId("enter_fullscreen", null);
+ clickOnElementId("exit_fullscreen", null);
assertFalse(getXWalkView().hasEnteredFullscreen());
} catch (Throwable e) {
e.printStackTrace();
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Test suite for OnRequestFocus().
+ */
+public class OnRequestFocusTest extends XWalkViewTestBase {
+ private TestHelperBridge.OnRequestFocusHelper mOnRequestFocusHelper;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mOnRequestFocusHelper = mTestHelperBridge.getOnRequestFocusHelper();
+ }
+
+ @SmallTest
+ @Feature({"OnRequestFocus"})
+ public void testOnRequestFocus() throws Throwable {
+ final String url = "file:///android_asset/www/request_focus_main.html";
+ int count = mOnRequestFocusHelper.getCallCount();
+
+ loadUrlSync(url);
+ clickOnElementId("left_frame", "LeftFrame");
+ mOnRequestFocusHelper.waitForCallback(count);
+ assertTrue(mOnRequestFocusHelper.getCalled());
+ }
+}
final int shouldOverrideUrlLoadingCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
final int onPageStartedCallCount = onPageStartedHelper.getCallCount();
setShouldOverrideUrlLoadingReturnValueOnUiThread(true);
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
assertEquals(onPageStartedCallCount, onPageStartedHelper.getCallCount());
setShouldOverrideUrlLoadingReturnValueOnUiThread(true);
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
final int shouldOverrideUrlLoadingCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
// After we load this URL we're certain that any in-flight callbacks for the previous
// navigation have been delivered.
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
}
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
assertEquals(httpPathOnServer,
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
}
getHtmlForPageWithJsReplaceLinkTo(redirectTargetUrl), "text/html", false);
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
}
CommonResources.makeHtmlPageWithSimpleLinkTo(redirectTargetUrl), "text/html", false);
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
assertEquals(redirectTargetUrl,
mShouldOverrideUrlLoadingHelper.getShouldOverrideUrlLoadingUrl());
setShouldOverrideUrlLoadingReturnValueOnUiThread(true);
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
// Some time around here true should be returned from the shouldOverrideUrlLoading
// callback causing the navigation caused by calling clickOnElementId to be ignored.
// We validate this by checking which pages were loaded on the server.
CommonResources.makeHtmlPageWithSimpleLinkTo(dataUrl), "text/html", false);
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
assertTrue("Expected URL that starts with 'data:' but got: <" +
false);
int callCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(callCount);
assertEquals(unsupportedSchemeUrl,
mShouldOverrideUrlLoadingHelper.getCallCount();
assertEquals(0, mWebServer.getRequestCount(REDIRECT_TARGET_PATH));
- clickOnElementId("link");
+ clickOnElementId("link", null);
// Wait for the target URL to be fetched from the server.
pollOnUiThread(new Callable<Boolean>() {
final int shouldOverrideUrlLoadingCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(shouldOverrideUrlLoadingCallCount);
int indirectLoadCallCount = mShouldOverrideUrlLoadingHelper.getCallCount();
loadUrlSync(pageWithLinkToRedirectUrl);
- clickOnElementId("link");
+ clickOnElementId("link", null);
mShouldOverrideUrlLoadingHelper.waitForCallback(indirectLoadCallCount, 3);
assertEquals(redirectTarget,
}
}
+ public class OnRequestFocusHelper extends CallbackHelper {
+ private boolean mCalled = false;
+
+ public boolean getCalled() {
+ assert getCallCount() > 0;
+ return mCalled;
+ }
+
+ public void notifyCalled(boolean called) {
+ mCalled = called;
+ notifyCalled();
+ }
+ }
+
private String mChangedTitle;
private final OnPageStartedHelper mOnPageStartedHelper;
private final OnPageFinishedHelper mOnPageFinishedHelper;
private final OnProgressChangedHelper mOnProgressChangedHelper;
private final ShouldOverrideUrlLoadingHelper mShouldOverrideUrlLoadingHelper;
private final OnScaleChangedHelper mOnScaleChangedHelper;
+ private final OnRequestFocusHelper mOnRequestFocusHelper;
public TestHelperBridge() {
mOnPageStartedHelper = new OnPageStartedHelper();
mOnProgressChangedHelper = new OnProgressChangedHelper();
mShouldOverrideUrlLoadingHelper = new ShouldOverrideUrlLoadingHelper();
mOnScaleChangedHelper = new OnScaleChangedHelper();
+ mOnRequestFocusHelper = new OnRequestFocusHelper();
}
public OnPageStartedHelper getOnPageStartedHelper() {
return mOnScaleChangedHelper;
}
+ public OnRequestFocusHelper getOnRequestFocusHelper() {
+ return mOnRequestFocusHelper;
+ }
+
public void onTitleChanged(String title) {
mChangedTitle = title;
mOnTitleUpdatedHelper.notifyCalled(title);
public void onScaleChanged(float scale) {
mOnScaleChangedHelper.notifyCalled(scale);
}
+
+ public void onRequestFocus() {
+ mOnRequestFocusHelper.notifyCalled(true);
+ }
}
public void onScaleChanged(XWalkView view, float oldScale, float newScale) {
mInnerContentsClient.onScaleChanged(newScale);
}
+
+ @Override
+ public void onRequestFocus(XWalkView view) {
+ mInnerContentsClient.onRequestFocus();
+ }
}
class TestXWalkUIClient extends TestXWalkUIClientBase {
});
}
- public void clickOnElementId(final String id) throws Exception {
+ public void clickOnElementId(final String id, String frameName) throws Exception {
+ String str;
+ if (frameName != null) {
+ str = "top.window." + "LeftFrame" + ".document.getElementById('" + id + "')";
+ } else {
+ str = "document.getElementById('" + id + "')";
+ }
+ final String script1 = str + " != null";
+ final String script2 = str + ".dispatchEvent(evObj);";
Assert.assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
@Override
public boolean isSatisfied() {
try {
- String idIsNotNull = executeJavaScriptAndWaitForResult(
- "document.getElementById('" + id + "') != null");
+ String idIsNotNull = executeJavaScriptAndWaitForResult(script1);
return idIsNotNull.equals("true");
} catch (Throwable t) {
t.printStackTrace();
String result = executeJavaScriptAndWaitForResult(
"var evObj = document.createEvent('Events'); " +
"evObj.initEvent('click', true, false); " +
- "document.getElementById('" + id + "').dispatchEvent(evObj);" +
+ script2 +
"console.log('element with id [" + id + "] clicked');");
} catch (Throwable t) {
t.printStackTrace();
--- /dev/null
+<html>
+<body>
+<a href="request_focus_right_frame1.html" id="left_frame" target="RightFrame">Click me</a>
+</body>
+</html>
--- /dev/null
+<html>
+<head>
+<script>
+document.get
+</script>
+</head>
+<frameset rows=50%,50%>
+ <frame src="request_focus_left_frame.html" name="LeftFrame" />
+ <frame src="request_focus_right_frame.html" name="RightFrame" />
+</frameset>
+</html>
--- /dev/null
+right frame
--- /dev/null
+another right frame
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.xwalk.runtime.test">
-
- <application>
- <uses-library android:name="android.test.runner" />
- <provider android:name="org.xwalk.runtime.client.test.TestContentProvider"
- android:authorities="org.xwalk.runtime.test.TestContentProvider" />
- </application>
-
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
- <instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="org.xwalk.runtime.shell"
- android:label="Test for org.xwalk.runtime" />
- <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>
+++ /dev/null
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// 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.test;
-
-import android.test.ActivityInstrumentationTestCase2;
-
-public class XWalkRuntimeTestBase
- extends ActivityInstrumentationTestCase2<XWalkRuntimeTestRunnerActivity> {
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- public XWalkRuntimeTestBase() {
- super(XWalkRuntimeTestRunnerActivity.class);
- }
-}
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
-import org.xwalk.app.runtime.XWalkRuntimeClient;
import org.xwalk.runtime.client.shell.XWalkRuntimeClientShellActivity;
import org.xwalk.test.util.XWalkRuntimeClientTestGeneric;
import org.xwalk.test.util.XWalkRuntimeClientTestUtilBase;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
-import org.xwalk.app.runtime.XWalkRuntimeClient;
import org.xwalk.runtime.client.embedded.shell.XWalkRuntimeClientEmbeddedShellActivity;
import org.xwalk.test.util.XWalkRuntimeClientTestGeneric;
import org.xwalk.test.util.XWalkRuntimeClientTestUtilBase;
import android.content.Context;
import android.test.ActivityInstrumentationTestCase2;
-import org.xwalk.app.runtime.XWalkRuntimeClient;
+import org.xwalk.app.runtime.XWalkRuntimeView;
import org.xwalk.app.XWalkRuntimeActivityBase;
import org.xwalk.test.util.XWalkRuntimeClientTestUtilBase.PageStatusCallback;
public class XWalkRuntimeClientTestGeneric<T extends XWalkRuntimeActivityBase>
extends ActivityInstrumentationTestCase2<T> {
- private XWalkRuntimeClient mRuntimeView;
+ private XWalkRuntimeView mRuntimeView;
XWalkRuntimeClientTestUtilBase mTestUtil;
@Override
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
- if (mRuntimeView == null || mRuntimeView.get() == null) {
+ if (mRuntimeView == null) {
mRuntimeView = activity.getRuntimeView();
}
mTestUtil = new XWalkRuntimeClientTestUtilBase(mRuntimeView,
import java.util.concurrent.TimeUnit;
import org.chromium.content.browser.test.util.CallbackHelper;
-import org.xwalk.app.runtime.XWalkRuntimeClient;
+import org.xwalk.app.runtime.XWalkRuntimeView;
-public class XWalkRuntimeClientTestUtilBase extends XWalkTestUtilBase<XWalkRuntimeClient> {
+public class XWalkRuntimeClientTestUtilBase extends XWalkTestUtilBase<XWalkRuntimeView> {
public class PageStatusCallback {
public void onPageStarted(String url) {
mCallbackHelpers.onPageStarted(url);
}
}
- public XWalkRuntimeClientTestUtilBase(XWalkRuntimeClient runtimeView,
+ public XWalkRuntimeClientTestUtilBase(XWalkRuntimeView runtimeView,
Instrumentation instrumentation) {
super(runtimeView, instrumentation);
}
+++ /dev/null
-// 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 "xwalk/tizen/browser/audio_session_manager.h"
-
-#include "base/logging.h"
-#include "xwalk/tizen/browser/browser_mediaplayer_manager.h"
-
-namespace tizen {
-
-AudioSessionManager::AudioSessionManager(
- BrowserMediaPlayerManager* manager,
- MediaPlayerID player_id,
- int process_id)
- : event_type_(ASM_EVENT_NONE),
- manager_(manager),
- handle_(-1),
- process_id_(process_id),
- player_id_(player_id) {
-}
-
-AudioSessionManager::~AudioSessionManager() {
- UnregisterAudioSessionManager();
-}
-
-bool AudioSessionManager::RegisterAudioSessionManager(
- ASM_sound_events_t event_type,
- ASM_sound_cb_t notify_callback,
- void* callback_data) {
- int error = 0;
- event_type_ = event_type;
-
- if (!ASM_register_sound(process_id_, &handle_,
- event_type_, ASM_STATE_NONE,
- notify_callback, callback_data,
- ASM_RESOURCE_NONE, &error)) {
- LOG(ERROR) << "Register audio session manager failed. errcode=" << error;
- return false;
- }
-
- return true;
-}
-
-bool AudioSessionManager::UnregisterAudioSessionManager() {
- int error = 0;
- if (!ASM_unregister_sound(handle_, event_type_, &error)) {
- LOG(ERROR) << "Unregister audio session manager failed. errcode=" << error;
- return false;
- }
-
- return true;
-}
-
-bool AudioSessionManager::SetSoundState(ASM_sound_states_t state) {
- int error = 0;
- if (!ASM_set_sound_state(handle_, event_type_, state,
- ASM_RESOURCE_NONE, &error)) {
- LOG(ERROR) << "Set sound state =" << state << "failed. errcode=" << error;
- return false;
- }
-
- return true;
-}
-
-} // namespace tizen
+++ /dev/null
-// 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 XWALK_TIZEN_BROWSER_AUDIO_SESSION_MANAGER_H_
-#define XWALK_TIZEN_BROWSER_AUDIO_SESSION_MANAGER_H_
-
-#include <audio-session-manager.h>
-#include "base/basictypes.h"
-
-namespace tizen {
-class BrowserMediaPlayerManager;
-
-typedef int MediaPlayerID;
-
-// This class manages communication between MediaPlayer and Audio
-// Session Manager. It also defines Media Session policy and update
-// the sound state to ASM server.
-class AudioSessionManager {
- public:
- AudioSessionManager(
- BrowserMediaPlayerManager* manager,
- MediaPlayerID player_id,
- int process_id);
- ~AudioSessionManager();
-
- // Register to ASM server
- bool RegisterAudioSessionManager(ASM_sound_events_t, ASM_sound_cb_t, void*);
- // Unregister to ASM server
- bool UnregisterAudioSessionManager();
-
- bool SetSoundState(ASM_sound_states_t);
- MediaPlayerID player_id() const { return player_id_; }
-
- BrowserMediaPlayerManager* media_player_manager() {
- return manager_;
- }
-
- private:
- ASM_sound_events_t event_type_;
- BrowserMediaPlayerManager* manager_;
- int handle_;
- int process_id_;
- MediaPlayerID player_id_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioSessionManager);
-};
-
-} // namespace tizen
-
-#endif // XWALK_TIZEN_BROWSER_AUDIO_SESSION_MANAGER_H_
+++ /dev/null
-# 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.
-
-#------------------------------------------------
-# Functions from audio-session-manager used in Crosswalk code.
-#------------------------------------------------
-bool ASM_register_sound(const int application_pid, int *asm_handle, ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, ASM_sound_cb_t callback, void* cb_data, ASM_resource_t mm_resource, int *error_code);
-bool ASM_unregister_sound(const int asm_handle, ASM_sound_events_t sound_event, int *error_code);
-bool ASM_set_sound_state(const int asm_handle, ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, ASM_resource_t mm_resource, int *error_code);
+++ /dev/null
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// 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 "xwalk/tizen/browser/audio_session_manager_init.h"
-
-#include "base/files/file_path.h"
-#include "base/lazy_instance.h"
-#include "xwalk/tizen/browser/audio_session_manager_stubs.h"
-
-using xwalk_tizen_browser::kModuleAudio_session_manager;
-using xwalk_tizen_browser::InitializeStubs;
-using xwalk_tizen_browser::StubPathMap;
-
-namespace tizen {
-
-static const base::FilePath::CharType kAsmModuleLib[] =
- FILE_PATH_LITERAL("libaudio-session-mgr.so.0");
-
-// Audio session manager must only be initialized once, so use a
-// LazyInstance to ensure this.
-class AudioSessionManagerInitializer {
- public:
- bool Initialize() {
- if (!tried_initialize_) {
- tried_initialize_ = true;
- StubPathMap paths;
-
- paths[kModuleAudio_session_manager].push_back(kAsmModuleLib);
- initialized_ = InitializeStubs(paths);
- }
- return initialized_;
- }
-
- private:
- friend struct base::DefaultLazyInstanceTraits<AudioSessionManagerInitializer>;
-
- AudioSessionManagerInitializer()
- : initialized_(false),
- tried_initialize_(false) {
- }
-
- bool initialized_;
- bool tried_initialize_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioSessionManagerInitializer);
-};
-
-static base::LazyInstance<AudioSessionManagerInitializer>::Leaky g_asm_library =
- LAZY_INSTANCE_INITIALIZER;
-
-bool InitializeAudioSessionManager() {
- return g_asm_library.Get().Initialize();
-}
-
-} // namespace tizen
+++ /dev/null
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// 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.
-
-// Contains code that should be used for initializing the
-// audio session manager library as a whole.
-
-#ifndef XWALK_TIZEN_BROWSER_AUDIO_SESSION_MANAGER_INIT_H_
-#define XWALK_TIZEN_BROWSER_AUDIO_SESSION_MANAGER_INIT_H_
-
-#include "content/common/content_export.h"
-
-namespace tizen {
-
-// Attempts to initialize the audio session manager library.
-// Returns true if everything was successfully initialized, false otherwise.
-CONTENT_EXPORT bool InitializeAudioSessionManager();
-
-} // namespace tizen
-
-#endif // XWALK_TIZEN_BROWSER_AUDIO_SESSION_MANAGER_INIT_H_
+++ /dev/null
-// The extra include header needed in the generated stub file for defining
-// various audio session manager types.
-
-extern "C" {
-
-#include <audio-session-manager.h>
-
-}
+++ /dev/null
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// 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 "xwalk/tizen/browser/browser_mediaplayer_manager.h"
-
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "xwalk/tizen/browser/audio_session_manager_init.h"
-#include "xwalk/tizen/common/media_player_messages.h"
-
-namespace tizen {
-
-BrowserMediaPlayerManager::BrowserMediaPlayerManager(
- content::RenderViewHost* render_view_host)
- : WebContentsObserver(content::WebContents::FromRenderViewHost(
- render_view_host)) {
-}
-
-BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {}
-
-BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
- content::RenderViewHost* render_view_host) {
- return new BrowserMediaPlayerManager(render_view_host);
-}
-
-bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(BrowserMediaPlayerManager, msg)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerInitialize, OnInitialize)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerStarted, OnStart)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerPaused, OnPause)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
- OnDestroyAllMediaPlayers)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-AudioSessionManager* BrowserMediaPlayerManager::GetAudioSessionManager(
- MediaPlayerID player_id) {
- for (ScopedVector<AudioSessionManager>::iterator it =
- audio_session_managers_.begin(); it != audio_session_managers_.end();
- ++it) {
- if ((*it)->player_id() == player_id)
- return *it;
- }
-
- return NULL;
-}
-
-ASM_cb_result_t BrowserMediaPlayerManager::AudioSessionEventPause(
- ASM_event_sources_t event_source,
- MediaPlayerID player_id) {
- switch (event_source) {
- case ASM_EVENT_SOURCE_CALL_START:
- case ASM_EVENT_SOURCE_ALARM_START:
- case ASM_EVENT_SOURCE_MEDIA:
- case ASM_EVENT_SOURCE_EMERGENCY_START:
- case ASM_EVENT_SOURCE_OTHER_PLAYER_APP:
- case ASM_EVENT_SOURCE_RESOURCE_CONFLICT:
- Send(new MediaPlayerMsg_MediaPlayerPause(routing_id(), player_id));
- return ASM_CB_RES_PAUSE;
- default:
- return ASM_CB_RES_NONE;
- }
-}
-
-ASM_cb_result_t BrowserMediaPlayerManager::AudioSessionEventPlay(
- ASM_event_sources_t event_source,
- MediaPlayerID player_id) {
- switch (event_source) {
- case ASM_EVENT_SOURCE_ALARM_END:
- Send(new MediaPlayerMsg_MediaPlayerPlay(routing_id(), player_id));
- return ASM_CB_RES_PLAYING;
- default:
- return ASM_CB_RES_NONE;
- }
-}
-
-static ASM_cb_result_t AudioSessionNotifyCallback(
- int handle,
- ASM_event_sources_t event_source,
- ASM_sound_commands_t command,
- unsigned int sound_status,
- void* callback_data) {
- AudioSessionManager* data =
- static_cast<AudioSessionManager*>(callback_data);
-
- BrowserMediaPlayerManager* manager = data->media_player_manager();
- if (command == ASM_COMMAND_STOP || command == ASM_COMMAND_PAUSE)
- return manager->AudioSessionEventPause(event_source, data->player_id());
- if (command == ASM_COMMAND_PLAY || command == ASM_COMMAND_RESUME)
- return manager->AudioSessionEventPlay(event_source, data->player_id());
-
- return ASM_CB_RES_NONE;
-}
-
-void BrowserMediaPlayerManager::OnInitialize(
- MediaPlayerID player_id,
- int process_id,
- const GURL& url) {
-
- // Initialize the audio session manager library.
- if (!InitializeAudioSessionManager()) {
- DLOG(WARNING) << "Failed on loading the audio session manager library";
- return;
- }
-
- RemoveAudioSessionManager(player_id);
- AudioSessionManager* session_manager =
- new AudioSessionManager(this, player_id, process_id);
-
- session_manager->RegisterAudioSessionManager(
- ASM_EVENT_SHARE_MMPLAYER,
- AudioSessionNotifyCallback,
- session_manager);
- session_manager->SetSoundState(ASM_STATE_PAUSE);
-
- AddAudioSessionManager(session_manager);
-}
-
-void BrowserMediaPlayerManager::OnDestroyAllMediaPlayers() {
- audio_session_managers_.clear();
-}
-
-void BrowserMediaPlayerManager::OnDestroyPlayer(MediaPlayerID player_id) {
- RemoveAudioSessionManager(player_id);
-}
-
-void BrowserMediaPlayerManager::OnPause(MediaPlayerID player_id) {
- AudioSessionManager* session_manager = GetAudioSessionManager(player_id);
- if (session_manager)
- session_manager->SetSoundState(ASM_STATE_PAUSE);
-}
-
-void BrowserMediaPlayerManager::OnStart(MediaPlayerID player_id) {
- AudioSessionManager* session_manager = GetAudioSessionManager(player_id);
- if (session_manager)
- session_manager->SetSoundState(ASM_STATE_PLAYING);
-}
-
-void BrowserMediaPlayerManager::AddAudioSessionManager(
- AudioSessionManager* session_manager) {
- DCHECK(!GetAudioSessionManager(session_manager->player_id()));
- audio_session_managers_.push_back(session_manager);
-}
-
-void BrowserMediaPlayerManager::RemoveAudioSessionManager(
- MediaPlayerID player_id) {
- for (ScopedVector<AudioSessionManager>::iterator it =
- audio_session_managers_.begin(); it != audio_session_managers_.end();
- ++it) {
- if ((*it)->player_id() == player_id) {
- audio_session_managers_.erase(it);
- break;
- }
- }
-}
-
-} // namespace tizen
+++ /dev/null
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// 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 XWALK_TIZEN_BROWSER_BROWSER_MEDIAPLAYER_MANAGER_H_
-#define XWALK_TIZEN_BROWSER_BROWSER_MEDIAPLAYER_MANAGER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "url/gurl.h"
-#include "xwalk/tizen/browser/audio_session_manager.h"
-
-namespace tizen {
-
-// This class manages all AudioSessionManager objects in the browser
-// process. It receives control operations from the render process, and
-// forwards them to corresponding AudioSessionManager object. Callbacks
-// from AudioSessionManager objects are converted to IPCs and then sent
-// to the render process.
-class CONTENT_EXPORT BrowserMediaPlayerManager
- : public content::WebContentsObserver {
- public:
- virtual ~BrowserMediaPlayerManager();
-
- // Returns a new instance.
- static BrowserMediaPlayerManager* Create(
- content::RenderViewHost* render_view_host);
-
- // WebContentsObserver overrides.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual AudioSessionManager* GetAudioSessionManager(
- MediaPlayerID player_id) OVERRIDE;
-
- ASM_cb_result_t AudioSessionEventPause(
- ASM_event_sources_t eventSource, MediaPlayerID player_id);
- ASM_cb_result_t AudioSessionEventPlay(
- ASM_event_sources_t eventSource, MediaPlayerID player_id);
-
- protected:
- explicit BrowserMediaPlayerManager(content::RenderViewHost* render_view_host);
-
- private:
- virtual void OnInitialize(MediaPlayerID player_id,
- int process_id, const GURL& url);
- virtual void OnDestroyAllMediaPlayers();
- virtual void OnDestroyPlayer(MediaPlayerID player_id);
- virtual void OnPause(MediaPlayerID player_id);
- virtual void OnStart(MediaPlayerID player_id);
-
- // Adds a audio session manager for the given player to the list.
- void AddAudioSessionManager(AudioSessionManager* session_manager);
-
- // Removes the audio session manager of given |player_id|.
- void RemoveAudioSessionManager(MediaPlayerID player_id);
-
- ScopedVector<AudioSessionManager> audio_session_managers_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserMediaPlayerManager);
-};
-
-} // namespace tizen
-
-#endif // XWALK_TIZEN_BROWSER_BROWSER_MEDIAPLAYER_MANAGER_H_
--- /dev/null
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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 "xwalk/tizen/browser/media/browser_mediaplayer_manager.h"
+
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "xwalk/tizen/common/media/media_player_messages.h"
+
+namespace tizen {
+
+BrowserMediaPlayerManager::BrowserMediaPlayerManager(
+ content::RenderFrameHost* render_frame_host,
+ MurphyResourceManager* resource_manager)
+ : render_frame_host_(render_frame_host),
+ resource_manager_(resource_manager) {
+}
+
+BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {}
+
+BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
+ content::RenderFrameHost* render_frame_host,
+ MurphyResourceManager* resource_manager) {
+ return new BrowserMediaPlayerManager(render_frame_host, resource_manager);
+}
+
+MurphyResource* BrowserMediaPlayerManager::GetMurphyResource(
+ MediaPlayerID player_id) {
+ for (ScopedVector<MurphyResource>::iterator it =
+ murphy_resources_.begin(); it != murphy_resources_.end();
+ ++it) {
+ if ((*it)->player_id() == player_id)
+ return *it;
+ }
+
+ return NULL;
+}
+
+int BrowserMediaPlayerManager::RoutingID() {
+ return render_frame_host_->GetRoutingID();
+}
+
+bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
+ return render_frame_host_->Send(msg);
+}
+
+void BrowserMediaPlayerManager::ResourceNotifyCallback(
+ mrp_res_resource_state_t state,
+ MediaPlayerID player_id) {
+
+ MurphyResource* resource = GetMurphyResource(player_id);
+
+ mrp_res_resource_state_t prev_state = resource->GetResourceState();
+
+ // Received a resource event from Murphy
+ switch (state) {
+ case MRP_RES_RESOURCE_AVAILABLE:
+ if (prev_state == MRP_RES_RESOURCE_ACQUIRED)
+ Send(new MediaPlayerMsg_MediaPlayerPause(RoutingID(), player_id));
+ case MRP_RES_RESOURCE_LOST:
+ if (prev_state == MRP_RES_RESOURCE_ACQUIRED ||
+ prev_state == MRP_RES_RESOURCE_LOST)
+ Send(new MediaPlayerMsg_MediaPlayerPause(RoutingID(), player_id));
+ break;
+ case MRP_RES_RESOURCE_ACQUIRED:
+ if (prev_state == MRP_RES_RESOURCE_LOST)
+ Send(new MediaPlayerMsg_MediaPlayerPlay(RoutingID(), player_id));
+ break;
+ case MRP_RES_RESOURCE_PENDING:
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void BrowserMediaPlayerManager::OnInitialize(
+ MediaPlayerID player_id,
+ int process_id,
+ const GURL& url) {
+ // Create murphy resource for the given player id.
+ if (resource_manager_ && resource_manager_->IsConnected()) {
+ MurphyResource* resource = new MurphyResource(this,
+ player_id, resource_manager_);
+ RemoveMurphyResource(player_id);
+ AddMurphyResource(resource);
+ }
+}
+
+void BrowserMediaPlayerManager::OnDestroyPlayer(MediaPlayerID player_id) {
+ RemoveMurphyResource(player_id);
+}
+
+void BrowserMediaPlayerManager::OnPause(MediaPlayerID player_id) {
+ if (MurphyResource* resource = GetMurphyResource(player_id))
+ resource->ReleaseResource();
+}
+
+void BrowserMediaPlayerManager::OnStart(MediaPlayerID player_id) {
+ if (MurphyResource* resource = GetMurphyResource(player_id))
+ resource->AcquireResource();
+}
+
+void BrowserMediaPlayerManager::AddMurphyResource(
+ MurphyResource* resource) {
+ DCHECK(!GetMurphyResource(resource->player_id()));
+ murphy_resources_.push_back(resource);
+}
+
+void BrowserMediaPlayerManager::RemoveMurphyResource(
+ MediaPlayerID player_id) {
+ for (ScopedVector<MurphyResource>::iterator it =
+ murphy_resources_.begin(); it != murphy_resources_.end();
+ ++it) {
+ if ((*it)->player_id() == player_id) {
+ murphy_resources_.erase(it);
+ break;
+ }
+ }
+}
+
+} // namespace tizen
--- /dev/null
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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 XWALK_TIZEN_BROWSER_MEDIA_BROWSER_MEDIAPLAYER_MANAGER_H_
+#define XWALK_TIZEN_BROWSER_MEDIA_BROWSER_MEDIAPLAYER_MANAGER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "url/gurl.h"
+#include "xwalk/tizen/browser/media/murphy_resource_manager.h"
+#include "xwalk/tizen/browser/media/murphy_resource.h"
+
+namespace tizen {
+
+// This class manages all MurphyResource objects in the browser process. It
+// receives control operations from the render process, and forwards them to
+// corresponding MurphyResource object. Callbacks from MurphyResource objects
+// are converted to IPCs and then sent to the render process.
+class CONTENT_EXPORT BrowserMediaPlayerManager {
+ public:
+ virtual ~BrowserMediaPlayerManager();
+
+ // Returns a new instance.
+ static BrowserMediaPlayerManager* Create(
+ content::RenderFrameHost* render_frame_host,
+ MurphyResourceManager* resource_manager);
+
+ virtual MurphyResource* GetMurphyResource(
+ MediaPlayerID player_id);
+
+ void ResourceNotifyCallback(mrp_res_resource_state_t state,
+ MediaPlayerID player_id);
+
+ int RoutingID();
+
+ // Helper function to send messages to RenderFrameObserver.
+ bool Send(IPC::Message* msg);
+
+ // Message handlers.
+ virtual void OnInitialize(MediaPlayerID player_id,
+ int process_id, const GURL& url);
+ virtual void OnDestroyPlayer(MediaPlayerID player_id);
+ virtual void OnPause(MediaPlayerID player_id);
+ virtual void OnStart(MediaPlayerID player_id);
+
+ protected:
+ explicit BrowserMediaPlayerManager(
+ content::RenderFrameHost* render_frame_host,
+ MurphyResourceManager* resource_manager);
+
+ private:
+ // Adds a murphy resource for the given player to the list.
+ void AddMurphyResource(MurphyResource* resource);
+
+ // Removes the murphy resource of given |player_id|.
+ void RemoveMurphyResource(MediaPlayerID player_id);
+
+ content::RenderFrameHost* const render_frame_host_;
+
+ MurphyResourceManager* resource_manager_;
+ ScopedVector<MurphyResource> murphy_resources_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserMediaPlayerManager);
+};
+
+} // namespace tizen
+
+#endif // XWALK_TIZEN_BROWSER_MEDIA_BROWSER_MEDIAPLAYER_MANAGER_H_
--- /dev/null
+// 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.
+
+#include "xwalk/tizen/browser/media/media_webcontents_observer.h"
+
+#include "content/public/browser/web_contents.h"
+#include "xwalk/tizen/browser/media/browser_mediaplayer_manager.h"
+#include "xwalk/tizen/browser/media/murphy_resource_manager.h"
+#include "xwalk/tizen/common/media/media_player_messages.h"
+
+namespace tizen {
+
+MediaWebContentsObserver::MediaWebContentsObserver(
+ content::RenderViewHost* render_view_host)
+ : WebContentsObserver(content::WebContents::FromRenderViewHost(
+ render_view_host)) {
+ resource_manager_.reset(new MurphyResourceManager());
+}
+
+MediaWebContentsObserver::~MediaWebContentsObserver() {}
+
+void MediaWebContentsObserver::RenderFrameDeleted(
+ content::RenderFrameHost* render_frame_host) {
+ uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
+ media_player_managers_.erase(key);
+}
+
+bool MediaWebContentsObserver::OnMessageReceived(
+ const IPC::Message& msg,
+ content::RenderFrameHost* render_frame_host) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserver, msg)
+ IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_MediaPlayerInitialize,
+ GetMediaPlayerManager(render_frame_host),
+ BrowserMediaPlayerManager::OnInitialize)
+ IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_MediaPlayerStarted,
+ GetMediaPlayerManager(render_frame_host),
+ BrowserMediaPlayerManager::OnStart)
+ IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_MediaPlayerPaused,
+ GetMediaPlayerManager(render_frame_host),
+ BrowserMediaPlayerManager::OnPause)
+ IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_DestroyMediaPlayer,
+ GetMediaPlayerManager(render_frame_host),
+ BrowserMediaPlayerManager::OnDestroyPlayer)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+BrowserMediaPlayerManager* MediaWebContentsObserver::GetMediaPlayerManager(
+ content::RenderFrameHost* render_frame_host) {
+ uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
+ if (!media_player_managers_.contains(key)) {
+ media_player_managers_.set(
+ key,
+ make_scoped_ptr(BrowserMediaPlayerManager::Create(render_frame_host,
+ resource_manager_.get())));
+ }
+
+ return media_player_managers_.get(key);
+}
+
+} // namespace tizen
--- /dev/null
+// 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.
+
+#ifndef XWALK_TIZEN_BROWSER_MEDIA_MEDIA_WEBCONTENTS_OBSERVER_H_
+#define XWALK_TIZEN_BROWSER_MEDIA_MEDIA_WEBCONTENTS_OBSERVER_H_
+
+#include "base/compiler_specific.h"
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "xwalk/tizen/browser/media/murphy_resource_manager.h"
+
+namespace tizen {
+
+class BrowserMediaPlayerManager;
+class RenderViewHost;
+
+// This class manages all RenderFrame based media related managers at the
+// browser side. It receives IPC messages from media RenderFrameObservers and
+// forwards them to the corresponding managers. The managers are responsible
+// for sending IPCs back to the RenderFrameObservers at the render side.
+class CONTENT_EXPORT MediaWebContentsObserver :
+ public content::WebContentsObserver {
+ public:
+ explicit MediaWebContentsObserver(content::RenderViewHost* render_view_host);
+ virtual ~MediaWebContentsObserver();
+
+ // WebContentsObserver implementations.
+ virtual void RenderFrameDeleted(
+ content::RenderFrameHost* render_frame_host) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ content::RenderFrameHost* render_frame_host) OVERRIDE;
+
+ // Gets the media player manager associated with |render_frame_host|. Creates
+ // a new one if it doesn't exist. The caller doesn't own the returned pointer.
+ BrowserMediaPlayerManager* GetMediaPlayerManager(
+ content::RenderFrameHost* render_frame_host);
+
+ private:
+ // Map from RenderFrameHost* to BrowserMediaPlayerManager.
+ typedef base::ScopedPtrHashMap<uintptr_t, BrowserMediaPlayerManager>
+ MediaPlayerManagerMap;
+ MediaPlayerManagerMap media_player_managers_;
+
+ scoped_ptr<MurphyResourceManager> resource_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserver);
+};
+
+} // namespace tizen
+
+#endif // XWALK_TIZEN_BROWSER_MEDIA_MEDIA_WEBCONTENTS_OBSERVER_H_
--- /dev/null
+// 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/tizen/browser/media/murphy_mainloop.h"
+
+#include <errno.h>
+#include <murphy/common/macros.h>
+#include <murphy/common/log.h>
+#include <murphy/common/mm.h>
+#include <sys/socket.h>
+
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_pump_libevent.h"
+#include "content/public/browser/browser_thread.h"
+
+//
+// The Murphy resource libraries don't have interfaces that would allow one
+// to take externally care of the IPC necessary for communicating with the
+// server (the policy decision making entity). Instead these libraries always
+// operate within the context of a Murphy mainloop abstraction which by design
+// can be set up to be pumped by an external event loop. The MurphyMainloop
+// class below creates a Murphy mainloop and takes care of the details of
+// adapting it to be pumped by the local MessageLoop infrastructure.
+//
+// The Murphy mainloop needs abstractions for I/O watches, timers, and deferred
+// callbacks from the hosting environment. If necessary it can get along with
+// just I/O watches and timers and emulate deferred callbacks by low-delay
+// timers. Murphy needs timers to be both cancellable and modifiable and it
+// deferred callbacks that can be disabled and re-enabled.
+//
+// The available infrastructure here offers the basic building blocks for all of
+// these but none of them are a perfect fit. Here is the summary of the tweaks
+// we need (in the hope) to get the Murphy mainloop running:
+//
+// 1) You can only do async I/O in the content::BrowserThread::IO thread.
+//
+// We're running in content::BrowserThread::UI so we can't manipulate
+// FileDescriptorWatchers there. To overcome this we need to relay all
+// operations on FileDescriptorWatchers to content::BrowserThread::IO
+// by PostTask. This will result in getting all the I/O events delivered
+// to content::BrowserThread::IO. However, since we don't want to set up
+// a (potentially) complex locking scheme to protect access to the mainloop
+// we also relay FileDescriptorWatcher notifications back to the UI thread
+// for processing. Finally to make sure there are no pending events in
+// flight by the time we destroy an I/O watch we essentially drive the
+// destructor through a full UI -> IO -> UI thread relay.
+//
+// 2) FileDescriptorWatchers don't have HUP events.
+//
+// As a POSIX-specific hack we MSG_PEEK and generate a syntetic HUP event
+// if we got 0 bytes.
+//
+// 3) You can't cancel a PostTask'd or PostDelayedTask'd task.
+//
+// This prevents us from having a straightforward mapping of deferred
+// callbacks and timers to these. To overcome this we use a 'timeout finger-
+// print' which is used to ignore timeout callbacks that should have been
+// cancelled if only there was a mechanism for it. The fingerprint in simply
+// a monotonically increasing integer which is stored in the timer and also
+// associated with a pending timeout. Whenever the timer is reconfigured
+// (delay updated, or timer disabled) the fingerpring is updated. Timeout
+// callbacks with mismatching fingerprints are ignored.
+//
+// Originally we simply scheduled a task from the I/O thread to the UI thread
+// for reading the pending epoll events there. But since poll/select is level-
+// triggered by default this caused a large amount of messages before the
+// scheduler got around to run the UI thread an read the events. Therefore now
+// the Murphy mainloop has been opened up for doing the actual event retrieval
+// externally to better support pumping it from xwalk. This now starts to be
+// hairier than I'm comfortable with... I think it'd be a better idea to run
+// the mainloop fully in the I/O thread, have the resource sets live in the I/O
+// thread also and have proxy object for them attached to the media backend
+// obejcts which would send requests and receive notifications to/from the
+// resource sets. We could avoid most of the threading related compliations
+// for pumping the mainloop...
+//
+// Additionally to the basic mainloop adaptation we also set up the Murphy
+// debugging and logging infrastructure to use the native logging infra as
+// a backend. You can control the Murphy logging and debugging by two
+// environment variables:
+//
+// XWALK_MURPHY_LOG:
+// A comma separated list of log levels, defaults to 'info,warning,error'
+//
+// XWALK_MURPHY_DEBUG:
+// A comma-separated list of Murphy debug sites, for instance
+// '@mainloop.c,@resource.c,mrp_resource_set_create'. Setting this to
+// '*' will turn all debug sites on.
+//
+
+
+// Environment variable names to used to control debugging and logging
+#define ENVVAR_DBG "XWALK_MURPHY_DEBUG"
+#define ENVVAR_LOG "XWALK_MURPHY_LOG"
+
+namespace {
+
+static void xwalklogger(void* data, mrp_log_level_t level, const char* file,
+ int line, const char* func, const char* format,
+ va_list ap) {
+ va_list cp;
+ char msg[1024], locbuf[1024];
+ const char* loc;
+
+ MRP_UNUSED(data);
+ MRP_UNUSED(file);
+ MRP_UNUSED(line);
+
+ va_copy(cp, ap);
+
+ if (level != MRP_LOG_DEBUG) {
+ loc = "";
+ } else {
+ snprintf(locbuf, sizeof(locbuf), "[%s] ", func ? func : "<unknown>");
+ loc = locbuf;
+ }
+
+ if (vsnprintf(msg, sizeof(msg), format, cp) < (ssize_t)sizeof(msg)) {
+ switch (level) {
+ case MRP_LOG_INFO: LOG(INFO) << loc << msg; break;
+ case MRP_LOG_WARNING: LOG(WARNING) << loc << msg; break;
+ case MRP_LOG_ERROR: LOG(ERROR) << loc << msg; break;
+ case MRP_LOG_DEBUG: DLOG(INFO) << loc << msg; break;
+ default: break;
+ }
+ }
+
+ va_end(cp);
+}
+
+// Helper function to check if we have a pending HUP on an fd.
+static int pending_hup(int fd) {
+ char buf;
+ int len, saved_errno;
+
+ saved_errno = errno;
+ len = recv(fd, &buf, 1, MSG_PEEK);
+ errno = saved_errno;
+
+ return len == 0;
+}
+
+} // namespace
+
+namespace tizen {
+
+// An I/O watch abstraction for Murphy mainloop integration.
+//
+// As stated above, FileDescriptorWatcher's can only be manipulated
+// in BrowserThread::IO. As we execute in BrowserThread::UI we need
+// to relay watch manipulation operations to the I/O thread and
+// relay events back to the UI thread.
+class IoWatch : public base::MessagePumpLibevent::Watcher {
+ public:
+ // Constructor. Saves context and relays the watch setup to the I/O thread.
+ IoWatch(MurphyMainloop* mainloop, int fd, mrp_io_event_t events,
+ void (*cb)(void* glue_data, void* id, int fd, mrp_io_event_t events,
+ void* user_data), void* user_data)
+ : mainloop_(mainloop),
+ fd_(fd),
+ events_(events),
+ cb_(cb),
+ user_data_(user_data),
+ dead_(false) {
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&IoWatch::StartWatch,
+ base::Unretained(this)));
+ }
+
+ // Request destruction. Mark dead, relay watch cleanup to the I/O thread.
+ // The destruction sequence is finished once StopWatch relays WatchStopped
+ // back to the UI thread.
+ void Delete() {
+ if (dead_)
+ return;
+ else
+ dead_ = true;
+
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&IoWatch::StopWatch,
+ base::Unretained(this)));
+ }
+
+ private:
+ // Perform watch setup. Run in the I/O thread.
+ void StartWatch() {
+ base::MessageLoopForIO::Mode mode;
+
+ if (events_ & (MRP_IO_EVENT_IN | MRP_IO_EVENT_OUT))
+ mode = base::MessageLoopForIO::WATCH_READ_WRITE;
+ else if (events_ & MRP_IO_EVENT_IN)
+ mode = base::MessageLoopForIO::WATCH_READ;
+ else if (events_ & MRP_IO_EVENT_OUT)
+ mode = base::MessageLoopForIO::WATCH_WRITE;
+ else
+ mode = base::MessageLoopForIO::WATCH_READ; // Hmm... not quite right.
+
+ const bool success = base::MessageLoopForIO::current()->WatchFileDescriptor(
+ fd_, true, mode, &w_, this);
+ CHECK(success) << "Failed to add I/O watch for fd " << fd_;
+ }
+
+ // Perform watch cleanup. Run in I/O thread.
+ void StopWatch() {
+ if (dead_)
+ return;
+ w_.StopWatchingFileDescriptor();
+
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&IoWatch::WatchStopped,
+ base::Unretained(this)));
+ }
+
+ // Finish the destruction sequence by self-deleting. Run in UI thread.
+ void WatchStopped() {
+ delete this;
+ }
+
+ // Watch readability event handler. Run in I/O thread. Relays dispatching
+ // to UI thread.
+ virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
+ if (dead_)
+ return;
+
+ mainloop_->Poll(this);
+
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&IoWatch::DispatchReadable,
+ base::Unretained(this)));
+ }
+
+ // Watch writability event handler. Run in I/O thread. Relays dispatching
+ // to UI thread.
+ virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {
+ if (dead_)
+ return;
+
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&IoWatch::DispatchWritable,
+ base::Unretained(this)));
+ }
+
+ // Dispatch readability events the the mainloop.
+ void DispatchReadable() {
+ mrp_io_event_t events;
+ if (dead_)
+ return;
+
+ if ((events_ & MRP_IO_EVENT_HUP) && pending_hup(fd_))
+ events = MRP_IO_EVENT_HUP;
+ else
+ events = MRP_IO_EVENT_IN;
+
+ mrp_debug("dispatching crosswalk event 0x%x for fd %d", events, fd_);
+ cb_(reinterpret_cast<void*>(mainloop_), reinterpret_cast<void*>(this),
+ fd_, events, user_data_);
+ }
+
+ // Dispatch writability events the the mainloop.
+ void DispatchWritable() {
+ mrp_io_event_t events;
+ if (dead_)
+ return;
+
+ events = MRP_IO_EVENT_OUT;
+ mrp_debug("dispatching crosswalk event 0x%x for fd %d", events, fd_);
+ cb_(reinterpret_cast<void*>(mainloop_), reinterpret_cast<void*>(this),
+ fd_, events, user_data_);
+ }
+
+ // Associated mainloop data: fd, event mask, callback, and user data.
+ MurphyMainloop* mainloop_;
+ int fd_;
+ mrp_io_event_t events_;
+ void (*cb_)(void* glue_data, void* id, int fd, mrp_io_event_t events,
+ void* user_data);
+ void* user_data_;
+
+ // FileDescriptorWatcher we use for I/O monitoring
+ base::MessagePumpLibevent::FileDescriptorWatcher w_;
+
+ // flag used to mark initiated destruction sequence
+ bool dead_;
+
+ // A self-destructing object, so we have a private destructor
+ virtual ~IoWatch() {
+ mrp_debug("Destructing I/O watch");
+ }
+};
+
+// A Timer abstraction for Murphy mainloop integration.
+//
+// Since posted tasks cannot be cancelled, we use the stamped Timeout
+// object to filter out callbacks for timers that have been cancelled
+// (or reconfigured).
+class Timer;
+
+class Timeout : public base::RefCounted<Timeout> {
+ public:
+ explicit Timeout(Timer* t)
+ : timer_(t),
+ stamp_(0),
+ pending_(false) {
+ // Release upon timer destruction. We need to keep this object around
+ // until then.
+ AddRef();
+ }
+
+ // Clear Timeout for destruction. After this point all events are ignored.
+ // We're just waiting for the last reference to be Release()'d which is
+ // immediate if we have no pending timeouts. Otherwise it ought to happen
+ // once the last timeout has expired.
+ void Delete() {
+ timer_ = NULL;
+ Release();
+ }
+
+ // Arm or rearm the timeout with the given delay.
+ void Arm(int delay) {
+ base::TimeDelta delta(base::TimeDelta::FromMilliseconds(delay));
+ InvalidatePending();
+ content::BrowserThread::PostDelayedTask(content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&Timeout::Expired,
+ this, stamp_), delta);
+
+ pending_ = true;
+ }
+
+ // Disable timeouts.
+ void Disable() {
+ InvalidatePending();
+ }
+
+ private:
+ // Invalidate any possible pending Timeouts.
+ inline void InvalidatePending() {
+ if (pending_)
+ stamp_++;
+ }
+
+ // Timeout handler callback. Filter cancelled timeouts, deliver valid
+ // timeouts to the parent Timer.
+ void Expired(unsigned int stamp);
+
+ ~Timeout() {
+ mrp_debug("destructing Timeout %p", this);
+ }
+
+ // We're refcounted and have a private destructor...
+ friend class base::RefCounted<Timeout>;
+
+ // Timer we're serving.
+ Timer* timer_;
+
+ // Fingerprint stamp.
+ unsigned int stamp_;
+
+ // Flag to mark if we have pending timeouts.
+ bool pending_;
+};
+
+class Timer {
+ public:
+ Timer(MurphyMainloop* mainloop, int delay,
+ void (*cb)(void* glue_data, void* id, void* user_data),
+ void* user_data)
+ : mainloop_(mainloop),
+ cb_(cb),
+ user_data_(user_data),
+ delay_(delay),
+ enabled_(true),
+ timeout_(NULL) {
+ timeout_ = new Timeout(this);
+ ReArm();
+ }
+
+ // Upon timer destruction, initiate timeout destruction sequence and release
+ // its initial reference.
+ ~Timer() {
+ timeout_->Delete();
+ }
+
+ // Change timer delay.
+ void SetDelay(int delay) {
+ delay_ = delay;
+ ReArm();
+ }
+
+ // Enable timer.
+ void Enable() {
+ if (!enabled_) {
+ enabled_ = true;
+ ReArm();
+ }
+ }
+
+ // Disable timer.
+ void Disable() {
+ enabled_ = false;
+ timeout_->Disable();
+ }
+
+ private:
+ // Re-arm the timer with the current delay if it is enabled.
+ void ReArm() {
+ if (!enabled_ || delay_ == -1)
+ return;
+
+ mrp_debug("rearming timer %p (delay %d)", this, delay_);
+
+ timeout_->Arm(delay_);
+ }
+
+ // Timeout handler callback.
+ void DispatchTimer() {
+ if (enabled_) {
+ mrp_debug("dispatching crosswalk timeout event %p", this);
+ cb_(reinterpret_cast<void*>(mainloop_), reinterpret_cast<void*>(this),
+ user_data_);
+ }
+
+ if (enabled_)
+ ReArm();
+ }
+
+ private:
+ // Let Timeout invoke DispatchTimer.
+ friend class Timeout;
+
+ // Associated mainloop data: timer callback and user data.
+ MurphyMainloop* mainloop_;
+ void (*cb_)(void* glue_data, void* id, void* user_data);
+ void* user_data_;
+
+ // Our timeout in milliseconds.
+ int delay_;
+
+ // Whether we're enabled.
+ bool enabled_;
+
+ // Our associated timeout.
+ Timeout* timeout_;
+};
+
+void Timeout::Expired(unsigned int stamp) {
+ if (timer_ == NULL || stamp != stamp_)
+ return;
+
+ pending_ = false;
+
+ timer_->DispatchTimer();
+}
+
+MurphyMainloop::MurphyMainloop(const char* log, const char* debug)
+ : mainloop_(NULL),
+ poll_id_(NULL) {
+ mrp_list_init(&poll_q_);
+ setupLogger(log, debug);
+
+ CHECK(setupMainloop());
+}
+
+MurphyMainloop::~MurphyMainloop() {
+ mrp_debug("destroying MurphyMainloop");
+ mrp_mainloop_destroy(mainloop_);
+}
+
+
+// Crosswalk mainloop abstraction operations
+void* MurphyMainloop::AddIo(void* glue_data, int fd, mrp_io_event_t events,
+ void (*cb)(void* glue_data, void* id, int fd, mrp_io_event_t events,
+ void* user_data), void* user_data) {
+
+ MurphyMainloop* self = static_cast<MurphyMainloop*>(glue_data);
+
+ CHECK(self->poll_id_ == NULL);
+
+ self->poll_id_ = new IoWatch(self, fd, events, cb, user_data);
+
+ mrp_debug("added I/O Watch %p for fd %d (glue_data: %p)", self->poll_id_, fd,
+ glue_data);
+
+ return self->poll_id_;
+}
+
+// static
+void MurphyMainloop::DelIo(void* glue_data, void* id) {
+ IoWatch* w = static_cast<IoWatch*>(id);
+
+ mrp_debug("deleting I/O Watch %p", id);
+ w->Delete();
+}
+
+
+extern "C" {
+ typedef struct {
+ mrp_list_hook_t hook;
+ void* buf;
+ size_t size;
+ } pollq_data_t;
+}
+
+
+void MurphyMainloop::Poll(void* id) {
+ pollq_data_t* item;
+
+ mrp_debug("polling pending epoll events for the mainloop (id: %p)", id);
+
+#if 0
+ CHECK(poll_id_ == id);
+ CHECK(poll_events_);
+#else
+ if (poll_id_ != id || !poll_events_)
+ return;
+#endif
+
+ item = reinterpret_cast<pollq_data_t *>(mrp_allocz(sizeof(*item)));
+
+ if (item == NULL)
+ return;
+
+ mrp_list_init(&item->hook);
+ item->size = poll_events_(id, mainloop_, &item->buf);
+
+ poll_lock_.Acquire();
+ mrp_list_append(&poll_q_, &item->hook);
+ poll_lock_.Release();
+}
+
+
+// static
+size_t MurphyMainloop::PollIo(void* glue_data,
+ void* id, void* buf, size_t size) {
+ MurphyMainloop* self = static_cast<MurphyMainloop*>(glue_data);
+ pollq_data_t* item;
+
+ mrp_debug("dispatching epoll events to the mainloop (id: %p)", id);
+
+#if 0
+ CHECK(self->poll_id_ == id);
+#else
+ if (self->poll_id_ != id)
+ return 0;
+#endif
+
+ self->poll_lock_.Acquire();
+ if (!mrp_list_empty(&self->poll_q_)) {
+ item = mrp_list_entry(self->poll_q_.next, pollq_data_t, hook);
+ mrp_list_delete(&item->hook);
+ } else {
+ item = NULL;
+ }
+
+ self->poll_lock_.Release();
+
+ if (item != NULL) {
+ CHECK(size >= item->size);
+
+ size = item->size;
+ memcpy(buf, item->buf, size);
+
+ mrp_free(item);
+ } else {
+ size = 0;
+ }
+
+ return size;
+}
+
+// static
+void* MurphyMainloop::AddTimer(void* glue_data, unsigned int msecs,
+ void (*cb)(void* glue_data, void* id, void* user_data),
+ void* user_data) {
+ MurphyMainloop* self = static_cast<MurphyMainloop*>(glue_data);
+ mrp_debug("adding Timer with %u msecs, %p user data", msecs, user_data);
+
+ return new Timer(self, static_cast<int>(msecs), cb, user_data);
+}
+
+// static
+void MurphyMainloop::DelTimer(void* glue_data, void* id) {
+ Timer* t = reinterpret_cast<Timer*>(id);
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("deleting Timer %p", id);
+ delete t;
+}
+
+// static
+void MurphyMainloop::ModTimer(void* glue_data, void* id, unsigned int msecs) {
+ Timer* t = reinterpret_cast<Timer*>(id);
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("modifying Timer %p to %u msecs", t, msecs);
+ t->SetDelay(msecs);
+}
+
+// static
+void* MurphyMainloop::AddDefer(void* glue_data,
+ void (*cb)(void* glue_data, void* id, void* user_data),
+ void* user_data) {
+ mrp_debug("adding deferred callback (cb:%p, user data:%p)", cb, user_data);
+ return AddTimer(glue_data, 0, cb, user_data);
+}
+
+// static
+void MurphyMainloop::DelDefer(void* glue_data, void* id) {
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("deleting deferred callback %p", id);
+
+ DelTimer(glue_data, id);
+}
+
+// static
+void MurphyMainloop::ModDefer(void* glue_data, void* id, int enabled) {
+ MRP_UNUSED(glue_data);
+ Timer* t = reinterpret_cast<Timer*>(id);
+
+ mrp_debug("%sabling deferred callback %p", enabled ? "en" : "dis", id);
+
+ if (enabled)
+ t->Enable();
+ else
+ t->Disable();
+}
+
+// static
+void MurphyMainloop::Unregister(void* data) {
+ MRP_UNUSED(data);
+
+ mrp_debug("unrgistering mainloop with data %p", data);
+}
+
+bool MurphyMainloop::setupMainloop() {
+ mainloop_ = mrp_mainloop_create();
+ mrp_set_io_event_mode(mainloop_, MRP_IO_TRIGGER_EDGE);
+
+ static mrp_superloop_ops_t ops = {
+ &MurphyMainloop::AddIo,
+ &MurphyMainloop::DelIo,
+ &MurphyMainloop::AddTimer,
+ &MurphyMainloop::DelTimer,
+ &MurphyMainloop::ModTimer,
+ &MurphyMainloop::AddDefer,
+ &MurphyMainloop::DelDefer,
+ &MurphyMainloop::ModDefer,
+ &MurphyMainloop::Unregister,
+ NULL,
+ &MurphyMainloop::PollIo,
+ };
+
+ if (mrp_set_superloop(mainloop_, &ops, this)) {
+ poll_events_ = ops.poll_events;
+ return true;
+ } else {
+ mrp_log_error("Failed to set up superloop.");
+ return false;
+ }
+}
+
+// Murphy crosswalk logging backend
+void MurphyMainloop::setupLogger(const char* logcfg, const char* dbgcfg) {
+ static bool registered = false;
+ const char *dbg, *log, *p, *n;
+ char site[1024];
+ size_t l;
+
+ if (registered)
+ return;
+
+ if (mrp_log_register_target("xwalk", xwalklogger, NULL))
+ mrp_log_set_target("xwalk");
+
+ // configure logging, environment variable overrides argument
+ if ((log = getenv(ENVVAR_LOG)) == NULL)
+ log = "none";
+
+ mrp_log_enable(mrp_log_parse_levels(log));
+
+ // configure debugging, environment variable overrides argument
+ if ((dbg = getenv(ENVVAR_DBG)) == NULL)
+ dbg = dbgcfg ? dbgcfg : "off";
+
+ if (strcmp(dbg, "off")) {
+ mrp_log_info("Enabling Murphy debugging (%s).", dbg);
+ mrp_debug_enable(true);
+
+ p = dbg;
+ while (p != NULL) {
+ n = strchr(p, ',');
+ l = n ? n - p : strlen(p);
+
+ if (l < sizeof(site) - 1) {
+ strncpy(site, p, l);
+ site[l] = '\0';
+ mrp_log_info("Enabling Murphy debug site '%s'.", site);
+ mrp_debug_set_config(site);
+ }
+ p = n ? n + 1 : NULL;
+ }
+ }
+ registered = true;
+}
+
+} // namespace tizen
--- /dev/null
+// 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_TIZEN_BROWSER_MEDIA_MURPHY_MAINLOOP_H_
+#define XWALK_TIZEN_BROWSER_MEDIA_MURPHY_MAINLOOP_H_
+
+#include <murphy/common/mainloop.h>
+#include <murphy/common/list.h>
+
+#include "base/logging.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/synchronization/lock.h"
+
+namespace tizen {
+
+class MurphyMainloop {
+ public:
+ explicit MurphyMainloop(const char* log = NULL, const char* debug = NULL);
+ virtual ~MurphyMainloop();
+ void Poll(void* id);
+
+ mrp_mainloop_t* getMainloop() {
+ return mainloop_;
+ }
+
+ private:
+ mrp_mainloop_t* mainloop_;
+ base::Lock poll_lock_;
+ size_t (*poll_events_)(void *id, mrp_mainloop_t *ml, void **events);
+ void* poll_id_;
+ mrp_list_hook_t poll_q_;
+
+ // set up Murphy logging to bridge to the native logging infra
+ static void setupLogger(const char* log, const char* debug);
+
+ // create and set up Murphy mainloop
+ bool setupMainloop();
+
+ // crosswalk mainloop abstraction operations
+ static void* AddIo(void* glue_data, int fd, mrp_io_event_t events,
+ void (*cb)(void* glue_data, void* id, int fd,
+ mrp_io_event_t events, void* user_data),
+ void* user_data);
+ static void DelIo(void* glue_data, void* id);
+ static size_t PollIo(void* glue_data, void* id, void* buf, size_t size);
+
+ static void* AddTimer(void* glue_data, unsigned int msecs,
+ void (*cb)(void* glue_data, void* id, void* user_data),
+ void* user_data);
+ static void DelTimer(void* glue_data, void* id);
+ static void ModTimer(void* glue_data, void* id, unsigned int msecs);
+
+ static void* AddDefer(void* glue_data,
+ void (*cb)(void* glue_data, void* id, void* user_data),
+ void* user_data);
+ static void DelDefer(void* glue_data, void* id);
+ static void ModDefer(void* glue_data, void* id, int enabled);
+
+ static void Unregister(void* data);
+};
+
+} // namespace tizen
+
+#endif // XWALK_TIZEN_BROWSER_MEDIA_MURPHY_MAINLOOP_H_
--- /dev/null
+// 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/tizen/browser/media/murphy_resource.h"
+
+#include "xwalk/tizen/browser/media/browser_mediaplayer_manager.h"
+
+namespace {
+
+const char kMediaApplicationClass[] = "player";
+const char kMediaStreamName[] = "audio_playback";
+const char kMediaRole[] = "browser";
+
+static void NotifyCallback(mrp_res_context_t* context,
+ const mrp_res_resource_set_t* resource_set,
+ void* callback_data) {
+ tizen::MurphyResource* resource =
+ static_cast<tizen::MurphyResource*> (callback_data);
+ tizen::BrowserMediaPlayerManager* manager = resource->media_player_manager();
+ if (!manager)
+ return;
+
+ manager->ResourceNotifyCallback(resource_set->state, resource->player_id());
+ resource->SetResourceState(resource_set->state);
+}
+
+} // namespace
+
+namespace tizen {
+
+MurphyResource::MurphyResource(
+ BrowserMediaPlayerManager* manager,
+ MediaPlayerID player_id,
+ MurphyResourceManager* resource_manager)
+ : manager_(manager),
+ player_id_(player_id),
+ resource_manager_(resource_manager),
+ resource_state_(MRP_RES_RESOURCE_PENDING) {
+ mrp_res_context_t* context = resource_manager_->GetContext();
+ if (!context)
+ return;
+
+ resource_set_ = mrp_res_create_resource_set(context,
+ kMediaApplicationClass, NotifyCallback, this);
+ if (!resource_set_)
+ return;
+
+ mrp_res_resource_t* resource = mrp_res_create_resource(
+ resource_set_, kMediaStreamName, true, true);
+
+ mrp_res_attribute_t* attr = mrp_res_get_attribute_by_name(
+ resource, "role");
+ if (attr)
+ mrp_res_set_attribute_string(attr, kMediaRole);
+
+ mrp_res_release_resource_set(resource_set_);
+}
+
+void MurphyResource::AcquireResource() {
+ if (!resource_manager_ || !resource_set_)
+ return;
+
+ // Call acquire
+ mrp_res_acquire_resource_set(resource_set_);
+}
+
+void MurphyResource::ReleaseResource() {
+ if (!resource_manager_ || !resource_set_)
+ return;
+
+ // Call release
+ mrp_res_release_resource_set(resource_set_);
+}
+
+MurphyResource::~MurphyResource() {
+ ReleaseResource();
+
+ if (!resource_manager_ || !resource_set_)
+ return;
+
+ // Delete resource set (and the resource inside it)
+ mrp_res_delete_resource_set(resource_set_);
+}
+
+} // namespace tizen
--- /dev/null
+// 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_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_H_
+#define XWALK_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_H_
+
+#include "xwalk/tizen/browser/media/murphy_resource_manager.h"
+
+namespace tizen {
+
+typedef int MediaPlayerID;
+
+class MurphyResource {
+ public:
+ MurphyResource(BrowserMediaPlayerManager* manager,
+ MediaPlayerID player_id,
+ MurphyResourceManager* resource_manager);
+ ~MurphyResource();
+
+ void AcquireResource();
+ void ReleaseResource();
+
+ mrp_res_resource_state_t GetResourceState() const { return resource_state_; }
+ void SetResourceState(mrp_res_resource_state_t state) {
+ resource_state_ = state;
+ }
+
+ MediaPlayerID player_id() const { return player_id_; }
+ BrowserMediaPlayerManager* media_player_manager() {
+ return manager_;
+ }
+
+ private:
+ BrowserMediaPlayerManager* manager_;
+ MediaPlayerID player_id_;
+ MurphyResourceManager* resource_manager_;
+
+ mrp_res_resource_set_t* resource_set_;
+ mrp_res_resource_state_t resource_state_;
+};
+
+} // namespace tizen
+
+#endif // XWALK_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_H_
--- /dev/null
+// 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/tizen/browser/media/murphy_resource_manager.h"
+
+#include "base/logging.h"
+
+namespace {
+
+static void NotifyCallback(mrp_res_context_t* context,
+ mrp_res_error_t error, void* callback_data) {
+ if (error != MRP_RES_ERROR_NONE) {
+ LOG(ERROR) << "Error message received from Murphy. errcode=" << error;
+ return;
+ }
+
+ if (context->state == MRP_RES_DISCONNECTED) {
+ tizen::MurphyResourceManager* resource =
+ static_cast<tizen::MurphyResourceManager*> (callback_data);
+ if (resource)
+ resource->DisconnectFromMurphy();
+ }
+}
+
+} // namespace
+
+namespace tizen {
+
+MurphyResourceManager::MurphyResourceManager()
+ : murphy_context_(NULL),
+ murphy_mainloop_(new MurphyMainloop()),
+ mainloop_(murphy_mainloop_->getMainloop()) {
+ // Connect to murphy.
+ ConnectToMurphy();
+}
+
+MurphyResourceManager::~MurphyResourceManager() {
+ DisconnectFromMurphy();
+}
+
+void MurphyResourceManager::ConnectToMurphy() {
+ if (murphy_context_) {
+ mrp_res_destroy(murphy_context_);
+ murphy_context_ = NULL;
+ }
+
+ if (!murphy_context_)
+ murphy_context_ = mrp_res_create(mainloop_, NotifyCallback, this);
+}
+
+bool MurphyResourceManager::IsConnected() const {
+ if (!murphy_context_)
+ return false;
+
+ return murphy_context_->state == MRP_RES_CONNECTED;
+}
+
+void MurphyResourceManager::DisconnectFromMurphy() {
+ if (!murphy_context_)
+ return;
+
+ mrp_res_destroy(murphy_context_);
+ murphy_context_ = NULL;
+}
+
+mrp_res_context_t* MurphyResourceManager::GetContext() {
+ return murphy_context_;
+}
+
+} // namespace tizen
--- /dev/null
+// 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_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_MANAGER_H_
+#define XWALK_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_MANAGER_H_
+
+#include <murphy/plugins/resource-native/libmurphy-resource/resource-api.h>
+
+#include "base/memory/scoped_ptr.h"
+#include "xwalk/tizen/browser/media/murphy_mainloop.h"
+
+namespace tizen {
+class BrowserMediaPlayerManager;
+
+class MurphyResourceManager {
+ public:
+ MurphyResourceManager();
+ ~MurphyResourceManager();
+
+ void ConnectToMurphy();
+ void DisconnectFromMurphy();
+ bool IsConnected() const;
+
+ mrp_res_context_t* GetContext();
+
+ private:
+ mrp_res_context_t* murphy_context_;
+ scoped_ptr<MurphyMainloop> murphy_mainloop_;
+ mrp_mainloop_t* mainloop_;
+};
+
+} // namespace tizen
+
+#endif // XWALK_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_MANAGER_H_
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_DestroyMediaPlayer, // NOLINT(*)
int /* player_id */)
-// Destroy all the players.
-IPC_MESSAGE_ROUTED0(MediaPlayerHostMsg_DestroyAllMediaPlayers) // NOLINT(*)
-
// Initialize a media player object with the given player_id.
IPC_MESSAGE_ROUTED3(MediaPlayerHostMsg_MediaPlayerInitialize, // NOLINT(*)
int /* player_id */,
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/tizen/renderer/mediaplayer_impl.h"
+#include "xwalk/tizen/renderer/media/mediaplayer_impl.h"
#include "content/public/renderer/render_view.h"
#include "third_party/WebKit/public/platform/WebURL.h"
namespace tizen {
MediaPlayerImpl::MediaPlayerImpl(
- blink::WebFrame* frame,
+ blink::WebLocalFrame* frame,
blink::WebMediaPlayerClient* client,
base::WeakPtr<content::WebMediaPlayerDelegate> delegate,
RendererMediaPlayerManager* manager,
const content::WebMediaPlayerParams& params)
: WebMediaPlayerImpl(frame, client, delegate, params),
+ client_(client),
manager_(manager) {
DCHECK(manager_);
}
}
-void MediaPlayerImpl::WillDestroyCurrentMessageLoop() {
- if (manager_)
- manager_->UnregisterMediaPlayer(player_id_);
- Detach();
-}
-
void MediaPlayerImpl::Detach() {
manager_ = NULL;
}
WebMediaPlayerImpl::pause();
}
+void MediaPlayerImpl::OnMediaPlayerPlay() {
+ WebMediaPlayerImpl::play();
+ client_->playbackStateChanged();
+}
+
+void MediaPlayerImpl::OnMediaPlayerPause() {
+ WebMediaPlayerImpl::pause();
+ client_->playbackStateChanged();
+}
+
} // namespace tizen
// found in the LICENSE file.
-#ifndef XWALK_TIZEN_RENDERER_MEDIAPLAYER_IMPL_H_
-#define XWALK_TIZEN_RENDERER_MEDIAPLAYER_IMPL_H_
+#ifndef XWALK_TIZEN_RENDERER_MEDIA_MEDIAPLAYER_IMPL_H_
+#define XWALK_TIZEN_RENDERER_MEDIA_MEDIAPLAYER_IMPL_H_
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/renderer/media/webmediaplayer_impl.h"
-#include "xwalk/tizen/renderer/renderer_mediaplayer_manager.h"
+#include "xwalk/tizen/renderer/media/renderer_mediaplayer_manager.h"
namespace tizen {
class MediaPlayerImpl : public content::WebMediaPlayerImpl {
public:
MediaPlayerImpl(
- blink::WebFrame* frame,
+ blink::WebLocalFrame* frame,
blink::WebMediaPlayerClient* client,
base::WeakPtr<content::WebMediaPlayerDelegate> delegate,
RendererMediaPlayerManager* manager,
virtual void play();
virtual void pause();
- // As we are closing the app, |main_loop_| is destroyed even before
- // this object gets destructed, so we need to know when |main_loop_|
- // is being destroyed and we can stop posting playback controls.
- virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
-
// Detach the player from its manager.
void Detach();
+ // Functions called when media player status changes.
+ void OnMediaPlayerPlay();
+ void OnMediaPlayerPause();
+
private:
void InitializeMediaPlayer(const blink::WebURL& url);
+ blink::WebMediaPlayerClient* client_;
+
// Manager for managing this object and for delegating method calls on
// Render Thread.
RendererMediaPlayerManager* manager_;
} // namespace tizen
-#endif // XWALK_TIZEN_RENDERER_MEDIAPLAYER_IMPL_H_
+#endif // XWALK_TIZEN_RENDERER_MEDIA_MEDIAPLAYER_IMPL_H_
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xwalk/tizen/renderer/renderer_mediaplayer_manager.h"
+#include "xwalk/tizen/renderer/media/renderer_mediaplayer_manager.h"
-#include "xwalk/tizen/common/media_player_messages.h"
-#include "xwalk/tizen/renderer/mediaplayer_impl.h"
+#include "xwalk/tizen/common/media/media_player_messages.h"
+#include "xwalk/tizen/renderer/media/mediaplayer_impl.h"
namespace tizen {
RendererMediaPlayerManager::RendererMediaPlayerManager(
- content::RenderView* render_view)
- : content::RenderViewObserver(render_view),
+ content::RenderFrame* render_frame)
+ : content::RenderFrameObserver(render_frame),
next_media_player_id_(0) {
}
MediaPlayerImpl* player = player_it->second;
player->Detach();
}
-
- Send(new MediaPlayerHostMsg_DestroyAllMediaPlayers(routing_id()));
}
bool RendererMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
void RendererMediaPlayerManager::OnPlayerPlay(MediaPlayerID player_id) {
if (MediaPlayerImpl* player = GetMediaPlayer(player_id))
- player->play();
+ player->OnMediaPlayerPlay();
}
void RendererMediaPlayerManager::OnPlayerPause(MediaPlayerID player_id) {
if (MediaPlayerImpl* player = GetMediaPlayer(player_id))
- player->pause();
+ player->OnMediaPlayerPause();
}
} // namespace tizen
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_TIZEN_RENDERER_RENDERER_MEDIAPLAYER_MANAGER_H_
-#define XWALK_TIZEN_RENDERER_RENDERER_MEDIAPLAYER_MANAGER_H_
+#ifndef XWALK_TIZEN_RENDERER_MEDIA_RENDERER_MEDIAPLAYER_MANAGER_H_
+#define XWALK_TIZEN_RENDERER_MEDIA_RENDERER_MEDIAPLAYER_MANAGER_H_
#include <map>
#include "base/basictypes.h"
-#include "content/public/renderer/render_view_observer.h"
+#include "content/public/renderer/render_frame_observer.h"
#include "url/gurl.h"
namespace tizen {
// Class for managing all the MediaPlayerImpl objects in the same
// RenderView.
-class RendererMediaPlayerManager : public content::RenderViewObserver {
+class RendererMediaPlayerManager : public content::RenderFrameObserver {
public:
// Constructs a RendererMediaPlayerManager object for the |render_view|.
- explicit RendererMediaPlayerManager(content::RenderView* render_view);
+ explicit RendererMediaPlayerManager(content::RenderFrame* render_frame);
virtual ~RendererMediaPlayerManager();
// RenderViewObserver overrides.
} // namespace tizen
-#endif // XWALK_TIZEN_RENDERER_RENDERER_MEDIAPLAYER_MANAGER_H_
+#endif // XWALK_TIZEN_RENDERER_MEDIA_RENDERER_MEDIAPLAYER_MANAGER_H_
]
-def PerformSerialize(output_path, generator):
+WRAPPER_PACKAGE = 'org.xwalk.core'
+BRIDGE_PACKAGE = 'org.xwalk.core.internal'
+
+
+def FormatPackagePath(folder, package):
+ return os.path.join(folder, os.path.sep.join(package.split('.')))
+
+
+def PerformSerialize(output_path, generator, package):
# Serialize the code.
- file_name = os.path.join(output_path, generator.GetGeneratedClassFileName())
+ file_name = os.path.join(FormatPackagePath(output_path, package),
+ generator.GetGeneratedClassFileName())
if not os.path.isdir(os.path.dirname(file_name)):
os.makedirs(os.path.dirname(file_name))
file_handle = open(file_name, 'w')
if java_data.class_type == 'interface':
interface_generator = InterfaceGenerator(java_data, class_loader)
interface_generator.RunTask()
- PerformSerialize(wrap_output, interface_generator)
+ PerformSerialize(wrap_output, interface_generator, WRAPPER_PACKAGE)
else:
# Generate Bridge code.
bridge_generator = BridgeGenerator(java_data, class_loader)
bridge_generator.RunTask()
# Serialize.
- PerformSerialize(bridge_output, bridge_generator)
+ PerformSerialize(bridge_output, bridge_generator, BRIDGE_PACKAGE)
# Generate Wrapper code.
wrapper_generator = WrapperGenerator(java_data, class_loader)
wrapper_generator.RunTask()
- PerformSerialize(wrap_output, wrapper_generator)
+ PerformSerialize(wrap_output, wrapper_generator, WRAPPER_PACKAGE)
def GenerateBindingForJavaDirectory(input_dir, bridge_output, wrap_output):
if helper_class is None:
return
f = open(helper_class, 'r')
- output = os.path.join(wrap_output, os.path.basename(helper_class))
+ output = os.path.join(FormatPackagePath(wrap_output, WRAPPER_PACKAGE),
+ os.path.basename(helper_class))
if not os.path.isdir(os.path.dirname(output)):
os.makedirs(os.path.dirname(output))
fo = open(output, 'w')
if line.startswith('package '):
fo.write('package org.xwalk.core;\n')
else:
- fo.write(line + '\n')
+ if 'Wrapper Only' in line:
+ pass
+ else:
+ fo.write(line + '\n')
fo.close()
f.close()
'../components/nacl.gyp:nacl_helper',
'../components/nacl.gyp:nacl_linux',
'../native_client/src/trusted/service_runtime/linux/nacl_bootstrap.gyp:nacl_helper_bootstrap',
+ '../ppapi/native_client/src/trusted/plugin/plugin.gyp:nacl_trusted_plugin',
],
}],
],
'xwalk_core_internal_test_apk',
'xwalk_core_shell_apk',
'xwalk_core_test_apk',
- 'xwalk_runtime_shell_apk',
'xwalk_runtime_client_embedded_shell_apk',
'xwalk_runtime_client_embedded_test_apk',
'xwalk_runtime_client_shell_apk',
],
},
{
- 'target_name': 'xwalk_core_internal_java',
- 'type': 'none',
- 'dependencies': [
- '../components/components.gyp:navigation_interception_java',
- '../components/components.gyp:web_contents_delegate_android_java',
- '../content/content.gyp:content_java',
- '../ui/android/ui_android.gyp:ui_java',
- 'xwalk_core_extensions_java',
- 'xwalk_core_strings',
- ],
- 'variables': {
- 'java_in_dir': 'runtime/android/core_internal',
- 'has_java_resources': 1,
- 'R_package': 'org.xwalk.core.internal',
- 'R_package_relpath': 'org/xwalk/core/internal',
- },
- 'includes': ['../build/java.gypi'],
- },
- {
'target_name': 'xwalk_core_strings',
'type': 'none',
'variables': {
'type': 'none',
'variables': {
'timestamp': '<(reflection_java_dir)/gen.timestamp',
+ 'internal_src': 'runtime/android/core_internal/src/org/xwalk/core/internal',
+ 'internal_java_sources': [
+ '>!@(find <(internal_src) -name "*.java")'
+ ],
},
'all_dependent_settings': {
'variables': {
'tools/reflection_generator/java_method.py',
'tools/reflection_generator/reflection_generator.py',
'tools/reflection_generator/wrapper_generator.py',
- '<(PRODUCT_DIR)/gen/xwalk_core_internal_java/xwalk_core_internal_java.jar',
+ '>@(internal_java_sources)',
],
'outputs': [
'<(timestamp)',
],
'action': [
'python', 'tools/reflection_generator/reflection_generator.py',
- '--input_dir', 'runtime/android/core_internal/src/org/xwalk/core/internal',
+ '--input_dir', '<(internal_src)',
'--bridge_output', '<(reflection_java_dir)/bridge',
'--wrap_output', '<(reflection_java_dir)/wrapper',
'--helper_class', 'runtime/android/core_internal/src/org/xwalk/core/internal/ReflectionHelper.java',
],
},
{
- #TODO(wang16): split it into internal and core.
- 'target_name': 'xwalk_core_java',
+ 'target_name': 'xwalk_core_internal_java',
'type': 'none',
'dependencies': [
- 'xwalk_core_internal_java',
+ '../components/components.gyp:navigation_interception_java',
+ '../components/components.gyp:web_contents_delegate_android_java',
+ '../content/content.gyp:content_java',
+ '../ui/android/ui_android.gyp:ui_java',
+ 'xwalk_core_extensions_java',
+ 'xwalk_core_strings',
'xwalk_core_reflection_layer_java_gen',
],
'variables': {
- 'java_in_dir': 'runtime/android/core',
- 'additional_input_paths': [ '>(reflection_layer_gen_timestamp)' ],
+ 'java_in_dir': 'runtime/android/core_internal',
+ 'has_java_resources': 1,
+ 'R_package': 'org.xwalk.core.internal',
+ 'R_package_relpath': 'org/xwalk/core/internal',
'generated_src_dirs': [
'<(reflection_java_dir)/bridge',
- '<(reflection_java_dir)/wrapper',
],
},
- 'includes': ['../build/java.gypi']
+ 'includes': ['../build/java.gypi'],
},
{
- 'target_name': 'xwalk_runtime_java',
+ 'target_name': 'xwalk_core_java',
'type': 'none',
'dependencies': [
- 'xwalk_core_java',
+ 'xwalk_core_reflection_layer_java_gen',
],
'variables': {
- 'java_in_dir': 'runtime/android/runtime',
- 'has_java_resources': 0,
+ 'java_in_dir': 'runtime/android/core',
+ 'additional_input_paths': [ '>(reflection_layer_gen_timestamp)' ],
+ 'generated_src_dirs': [
+ '<(reflection_java_dir)/wrapper',
+ ],
},
- 'includes': ['../build/java.gypi'],
+ 'includes': ['../build/java.gypi']
},
{
'target_name': 'xwalk_core_jar_jni',
'type': 'none',
'dependencies': [
'libxwalkcore',
- 'xwalk_core_extensions_java',
- 'xwalk_runtime_java',
+ 'xwalk_core_internal_java',
'xwalk_runtime_lib_apk_extension',
'xwalk_runtime_lib_apk_pak',
],
],
},
{
- 'target_name': 'xwalk_app_runtime_client_java',
- 'type': 'none',
- 'dependencies': [
- 'generate_xwalk_runtime_client_version',
- ],
- 'variables': {
- 'java_in_dir': 'app/android/runtime_client',
- 'generated_src_dirs': [ '<(SHARED_INTERMEDIATE_DIR)/version_java' ],
- },
- 'includes': ['../build/java.gypi'],
- },
- {
- 'target_name': 'xwalk_app_runtime_activity_java',
- 'type': 'none',
- 'dependencies': [
- 'xwalk_app_runtime_client_java',
- ],
- 'variables': {
- 'java_in_dir': 'app/android/runtime_activity',
- },
- 'includes': ['../build/java.gypi'],
- },
- {
'target_name': 'xwalk_app_hello_world_apk',
'type': 'none',
'dependencies': [
- 'xwalk_app_runtime_activity_java',
+ 'xwalk_app_runtime_java',
],
'variables': {
'apk_name': 'XWalkAppHelloWorld',
'target_name': 'xwalk_app_template_apk',
'type': 'none',
'dependencies': [
- 'xwalk_app_runtime_activity_java',
+ 'xwalk_app_runtime_java',
],
'variables': {
'apk_name': 'XWalkAppTemplate',
'type': 'none',
'dependencies': [
'generate_xwalk_runtime_client_version',
+ 'xwalk_core_java',
],
'variables': {
'java_in_dir': 'app/android/runtime_activity',
'type': 'none',
'dependencies': [
'xwalk_app_runtime_java',
- 'xwalk_runtime_java',
+ 'xwalk_app_template_apk',
'xwalk_core_library',
],
'actions': [
'type': 'none',
'dependencies': [
'xwalk_test_util_java',
- 'xwalk_app_runtime_client_java',
- 'xwalk_app_runtime_activity_java',
+ 'xwalk_app_runtime_java',
],
'variables': {
'java_in_dir': 'test/android/util/runtime_client',
'../third_party/android_tools/android_tools.gyp:android_support_v13_javalib',
'libxwalkcore',
'xwalk_core_extensions_java',
+ 'xwalk_core_internal_java',
'xwalk_core_java',
'xwalk_core_shell_apk_pak',
],
'native_lib_target': 'libxwalkcore',
'additional_input_paths': [
'<(PRODUCT_DIR)/xwalk_xwview/assets/www/index.html',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/www/request_focus_left_frame.html',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/www/request_focus_main.html',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/www/request_focus_right_frame.html',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/www/request_focus_right_frame1.html',
'<(PRODUCT_DIR)/xwalk_xwview/assets/xwalk.pak',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/jsapi/contacts_api.js',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/jsapi/device_capabilities_api.js',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/jsapi/launch_screen_api.js',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/jsapi/messaging_api.js',
+ '<(PRODUCT_DIR)/xwalk_xwview/assets/jsapi/presentation_api.js',
],
'conditions': [
['icu_use_data_file_flag==1', {
'destination': '<(PRODUCT_DIR)/xwalk_xwview/assets/www',
'files': [
'test/android/data/index.html',
+ 'test/android/data/request_focus_left_frame.html',
+ 'test/android/data/request_focus_main.html',
+ 'test/android/data/request_focus_right_frame.html',
+ 'test/android/data/request_focus_right_frame1.html',
],
- }
+ },
+ {
+ 'destination': '<(PRODUCT_DIR)/xwalk_xwview/assets/jsapi',
+ 'files': [
+ 'experimental/launch_screen/launch_screen_api.js',
+ 'experimental/presentation/presentation_api.js',
+ 'runtime/android/core_internal/src/org/xwalk/core/internal/extension/api/contacts/contacts_api.js',
+ 'runtime/android/core_internal/src/org/xwalk/core/internal/extension/api/device_capabilities/device_capabilities_api.js',
+ 'runtime/android/core_internal/src/org/xwalk/core/internal/extension/api/messaging/messaging_api.js',
+ ],
+ },
],
'includes': [ '../build/java_apk.gypi' ],
},
'is_test_apk': 1,
'additional_input_paths': [
'<(PRODUCT_DIR)/xwalk_xwview_test/assets/add_js_interface.html',
- '<(PRODUCT_DIR)/xwalk_internal_xwview_test/assets/echo.html',
- '<(PRODUCT_DIR)/xwalk_internal_xwview_test/assets/echoSync.html',
- '<(PRODUCT_DIR)/xwalk_internal_xwview_test/assets/framesEcho.html',
+ '<(PRODUCT_DIR)/xwalk_xwview_test/assets/echo.html',
+ '<(PRODUCT_DIR)/xwalk_xwview_test/assets/echoSync.html',
+ '<(PRODUCT_DIR)/xwalk_xwview_test/assets/framesEcho.html',
'<(PRODUCT_DIR)/xwalk_xwview_test/assets/fullscreen_enter_exit.html',
'<(PRODUCT_DIR)/xwalk_xwview_test/assets/index.html',
'<(PRODUCT_DIR)/xwalk_xwview_test/assets/scale_changed.html',
'includes': [ '../build/apk_test.gypi' ],
},
{
- 'target_name': 'xwalk_runtime_shell_apk',
- 'type': 'none',
- 'dependencies': [
- 'libxwalkcore',
- # Runtime code is also built by this target.
- 'xwalk_runtime_java',
- 'xwalk_runtime_shell_apk_pak',
- ],
- 'variables': {
- 'apk_name': 'XWalkRuntimeShell',
- 'java_in_dir': 'runtime/android/runtime_shell',
- 'resource_dir': 'runtime/android/runtime_shell/res',
- 'native_lib_target': 'libxwalkcore',
- 'additional_input_paths': [
- '<(PRODUCT_DIR)/xwalk_runtime/assets/xwalk.pak',
- ],
- 'conditions': [
- ['icu_use_data_file_flag==1', {
- 'additional_input_paths': [
- '<(PRODUCT_DIR)/xwalk_runtime/assets/icudtl.dat',
- ],
- }],
- ],
- 'asset_location': '<(PRODUCT_DIR)/xwalk_runtime/assets',
- },
- 'includes': [ '../build/java_apk.gypi' ],
- },
- {
- 'target_name': 'xwalk_runtime_shell_apk_pak',
- 'type': 'none',
- 'dependencies': [
- 'xwalk_pak',
- ],
- 'copies': [
- {
- 'destination': '<(PRODUCT_DIR)/xwalk_runtime/assets',
- 'files': [
- '<(PRODUCT_DIR)/xwalk.pak',
- ],
- 'conditions': [
- ['icu_use_data_file_flag==1', {
- 'files': [
- '<(PRODUCT_DIR)/icudtl.dat',
- ],
- }],
- ],
- },
- ],
- },
- {
- 'target_name': 'xwalk_runtime_shell_apk_java',
- 'type': 'none',
- 'dependencies': [
- 'xwalk_runtime_shell_apk',
- ],
- 'includes': [ '../build/apk_fake_jar.gypi' ],
- },
- {
'target_name': 'xwalk_runtime_client_shell_apk',
'type': 'none',
'dependencies': [
- 'xwalk_app_runtime_client_java',
- 'xwalk_app_runtime_activity_java',
+ 'xwalk_app_runtime_java',
'xwalk_runtime_client_test_utils_java',
],
'variables': {
'type': 'none',
'dependencies': [
'libxwalkcore',
- 'xwalk_app_runtime_client_java',
- 'xwalk_app_runtime_activity_java',
- 'xwalk_runtime_java',
+ 'xwalk_app_runtime_java',
+ 'xwalk_core_internal_java',
'xwalk_runtime_client_embedded_shell_apk_pak',
'xwalk_runtime_client_test_utils_java',
],
],
},
{
- 'target_name': 'xwalk_runtime_test_apk',
- 'type': 'none',
- 'dependencies': [
- '../base/base.gyp:base_java_test_support',
- '../content/content_shell_and_tests.gyp:content_java_test_support',
- '../net/net.gyp:net_java_test_support',
- '../tools/android/forwarder2/forwarder.gyp:forwarder2',
- '../tools/android/md5sum/md5sum.gyp:md5sum',
- 'xwalk_runtime_shell_apk_java',
- ],
- 'variables': {
- 'apk_name': 'XWalkRuntimeTest',
- 'java_in_dir': 'test/android/runtime/javatests',
- 'is_test_apk': 1,
- },
- 'includes': [ '../build/java_apk.gypi' ],
- },
- {
'target_name': 'xwalk_runtime_client_test_apk',
'type': 'none',
'dependencies': [
'dependencies': [
'libxwalkcore',
'xwalk_core_extensions_java',
+ 'xwalk_core_internal_java',
'xwalk_core_java',
'xwalk_core_shell_apk_pak',
],
'variables': {
'api_files': [
'<(DEPTH)/xwalk/runtime/android/core/src/org/xwalk/core/JavascriptInterface.java',
- '>(reflection_gen_dir)/wrapper/XWalkExtension.java',
- '>(reflection_gen_dir)/wrapper/XWalkJavascriptResult.java',
- '>(reflection_gen_dir)/wrapper/XWalkNavigationHistory.java',
- '>(reflection_gen_dir)/wrapper/XWalkNavigationItem.java',
- '>(reflection_gen_dir)/wrapper/XWalkPreferences.java',
- '>(reflection_gen_dir)/wrapper/XWalkResourceClient.java',
- '>(reflection_gen_dir)/wrapper/XWalkUIClient.java',
- '>(reflection_gen_dir)/wrapper/XWalkView.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkExtension.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkJavascriptResult.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkNavigationHistory.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkNavigationItem.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkPreferences.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkResourceClient.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkUIClient.java',
+ '>(reflection_gen_dir)/wrapper/org/xwalk/core/XWalkView.java',
],
'docs': '<(PRODUCT_DIR)/xwalk_core_library_docs',
},
'type': 'none',
'dependencies': [
'libxwalkcore',
+ 'xwalk_core_internal_java',
'xwalk_core_java',
],
'variables': {
'target_name': 'xwalk_core_library_java',
'type': 'none',
'dependencies': [
+ 'xwalk_core_internal_java',
'xwalk_core_java',
'xwalk_core_library_empty_embedder_apk',
],
],
'action': [
'python', '<(DEPTH)/xwalk/build/android/generate_xwalk_core_library_aar.py',
- '-s', '<(DEPTH)',
'-t', '<(PRODUCT_DIR)',
],
},
],
'sources': [
'application/common/application_storage_impl_unittest.cc',
- 'application/common/installer/package_unittest.cc',
+ 'application/common/package/package_unittest.cc',
'application/common/application_unittest.cc',
'application/common/application_file_util_unittest.cc',
'application/common/id_util_unittest.cc',