Upstream version 6.34.113.0 27/19027/1 accepted/tizen/generic/20140404.092229 accepted/tizen/ivi/20140409.182045 submit/tizen/20140404.082331
authorEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Fri, 4 Apr 2014 08:14:11 +0000 (08:14 +0000)
committerEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Fri, 4 Apr 2014 08:14:11 +0000 (08:14 +0000)
Upstream commit-id 7088b1669e5a2fb54fbd52cc4420e5769d859632

Change-Id: I414bcd47d2d419bb46a449d23fe9dde0b0389c2d
Signed-off-by: Eurogiciel-BOT <eurogiciel.tizen@gmail.com>
135 files changed:
packaging/crosswalk-2.31-enable-VAVDA-with-EGL.patch [deleted file]
packaging/crosswalk.spec
src/PRESUBMIT.py
src/base/base.gyp
src/base/base.gypi
src/base/message_loop/message_loop.h
src/build/util/LASTCHANGE
src/media/audio/pulse/pulse.sigs
src/media/audio/pulse/pulse_util.cc
src/ozone/impl/ozone_display.cc
src/ozone/impl/ozone_display.h
src/ozone/impl/surface_factory_wayland.cc
src/ozone/impl/surface_factory_wayland.h
src/ozone/impl/window_tree_host_delegate_wayland.cc
src/ozone/impl/window_tree_host_delegate_wayland.h
src/tools/android/forwarder2/forwarder.gyp
src/ui/views/views.gyp
src/v8/build/features.gypi
src/v8/src/bootstrapper.cc
src/v8/src/log.cc
src/v8/src/log.h
src/v8/src/objects.h
src/v8/src/third_party/xdk/xdk-agent.cc [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-agent.h [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-code-map.cc [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-code-map.h [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-types.h [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-v8.cc [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-v8.gyp [new file with mode: 0644]
src/v8/src/third_party/xdk/xdk-v8.h [new file with mode: 0644]
src/v8/tools/check-static-initializers.sh
src/v8/tools/gyp/v8.gyp
src/xwalk/DEPS.xwalk
src/xwalk/VERSION
src/xwalk/app/android/app_template/src/org/xwalk/app/template/AppTemplateActivity.java
src/xwalk/app/tools/android/customize.py
src/xwalk/app/tools/android/make_apk.py
src/xwalk/app/tools/android/make_apk_test.py
src/xwalk/app/tools/android/manifest_json_parser.py
src/xwalk/app/tools/android/test_data/manifest/icons/icon_144.png [new file with mode: 0644]
src/xwalk/app/tools/android/test_data/manifest/icons/icon_48.png [new file with mode: 0644]
src/xwalk/app/tools/android/test_data/manifest/icons/icon_72.png [new file with mode: 0644]
src/xwalk/app/tools/android/test_data/manifest/icons/icon_96.png [new file with mode: 0644]
src/xwalk/app/tools/android/test_data/manifest/manifest.json
src/xwalk/app/tools/android/test_data/manifest/manifest_app_launch_local_path.json
src/xwalk/app/tools/android/test_data/manifest/manifest_icon.json [new file with mode: 0644]
src/xwalk/application/application_resources.grd
src/xwalk/application/browser/application.cc
src/xwalk/application/browser/application.h
src/xwalk/application/browser/application_service.cc
src/xwalk/application/browser/application_system.cc
src/xwalk/application/browser/installer/package.cc
src/xwalk/application/browser/installer/package.h
src/xwalk/application/browser/installer/wgt_package.cc
src/xwalk/application/browser/installer/xpk_package.cc
src/xwalk/application/browser/installer/xpk_package.h
src/xwalk/application/common/application_data.cc
src/xwalk/application/common/application_data.h
src/xwalk/application/common/application_manifest_constants.cc
src/xwalk/application/common/application_manifest_constants.h
src/xwalk/application/common/manifest_handler.cc
src/xwalk/application/common/manifest_handlers/navigation_handler.cc [new file with mode: 0644]
src/xwalk/application/common/manifest_handlers/navigation_handler.h [new file with mode: 0644]
src/xwalk/application/common/manifest_handlers/navigation_handler_unittest.cc [new file with mode: 0644]
src/xwalk/application/common/manifest_handlers/tizen_application_handler.cc [new file with mode: 0644]
src/xwalk/application/common/manifest_handlers/tizen_application_handler.h [new file with mode: 0644]
src/xwalk/application/common/manifest_handlers/widget_handler.cc
src/xwalk/application/common/manifest_handlers/widget_handler_unittest.cc [new file with mode: 0644]
src/xwalk/application/extension/application_widget_api.js
src/xwalk/application/extension/application_widget_common_api.js [new file with mode: 0644]
src/xwalk/application/extension/application_widget_extension.cc
src/xwalk/application/extension/application_widget_extension.h
src/xwalk/application/extension/application_widget_storage.cc [new file with mode: 0644]
src/xwalk/application/extension/application_widget_storage.h [new file with mode: 0644]
src/xwalk/application/tools/linux/xwalk_launcher_main.cc
src/xwalk/application/xwalk_application.gypi
src/xwalk/build/common.gypi
src/xwalk/gyp_xwalk
src/xwalk/packaging/crosswalk-2.31-enable-VAVDA-with-EGL.patch [deleted file]
src/xwalk/packaging/crosswalk.spec
src/xwalk/runtime/android/core/src/org/xwalk/core/SslErrorHandler.java [deleted file]
src/xwalk/runtime/android/core/src/org/xwalk/core/SslUtil.java [new file with mode: 0644]
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkContent.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkContentsClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkContentsClientBridge.java
src/xwalk/runtime/android/core/src/org/xwalk/core/XWalkDefaultClient.java
src/xwalk/runtime/android/core/src/org/xwalk/core/extension/api/contacts/ContactFinder.java
src/xwalk/runtime/android/core/src/org/xwalk/core/extension/api/contacts/ContactSaver.java
src/xwalk/runtime/android/core/src/org/xwalk/core/extension/api/contacts/ContactUtils.java
src/xwalk/runtime/android/core/src/org/xwalk/core/extension/api/contacts/contacts_api.js
src/xwalk/runtime/android/core/strings/android_xwalk_strings.grd
src/xwalk/runtime/android/runtime/src/org/xwalk/runtime/XWalkClientForTest.java
src/xwalk/runtime/app/android/xwalk_main_delegate_android.cc
src/xwalk/runtime/browser/android/renderer_host/xwalk_render_view_host_ext.cc
src/xwalk/runtime/browser/android/xwalk_content.cc
src/xwalk/runtime/browser/android/xwalk_contents_client_bridge.cc
src/xwalk/runtime/browser/android/xwalk_contents_client_bridge_base.cc
src/xwalk/runtime/browser/android/xwalk_contents_client_bridge_base.h
src/xwalk/runtime/browser/android/xwalk_cookie_access_policy.cc
src/xwalk/runtime/browser/android/xwalk_cookie_access_policy.h
src/xwalk/runtime/browser/android/xwalk_request_interceptor.cc
src/xwalk/runtime/browser/runtime_context.cc
src/xwalk/runtime/browser/runtime_context.h
src/xwalk/runtime/browser/ui/native_app_window_tizen.cc
src/xwalk/runtime/browser/ui/native_app_window_tizen.h
src/xwalk/runtime/browser/ui/native_app_window_views.cc
src/xwalk/runtime/browser/xwalk_browser_main_parts.cc
src/xwalk/runtime/browser/xwalk_content_browser_client.cc
src/xwalk/runtime/browser/xwalk_content_browser_client.h
src/xwalk/runtime/common/xwalk_common_message_generator.cc [new file with mode: 0644]
src/xwalk/runtime/common/xwalk_common_message_generator.h [new file with mode: 0644]
src/xwalk/runtime/common/xwalk_common_messages.cc [new file with mode: 0644]
src/xwalk/runtime/common/xwalk_common_messages.h [new file with mode: 0644]
src/xwalk/runtime/common/xwalk_paths.cc
src/xwalk/runtime/common/xwalk_paths.h
src/xwalk/runtime/renderer/xwalk_content_renderer_client.cc
src/xwalk/runtime/renderer/xwalk_content_renderer_client.h
src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.cc [new file with mode: 0644]
src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.h [new file with mode: 0644]
src/xwalk/sysapps/device_capabilities/device_capabilities.idl
src/xwalk/sysapps/device_capabilities/device_capabilities_api_browsertest.html
src/xwalk/sysapps/device_capabilities/display_info_provider.cc
src/xwalk/sysapps/raw_socket/raw_socket.idl
src/xwalk/sysapps/raw_socket/raw_socket_api.js
src/xwalk/sysapps/raw_socket/raw_socket_api_browsertest.html
src/xwalk/sysapps/raw_socket/raw_socket_extension.cc
src/xwalk/sysapps/raw_socket/raw_socket_extension.h
src/xwalk/sysapps/raw_socket/udp_socket.idl [new file with mode: 0644]
src/xwalk/sysapps/raw_socket/udp_socket_object.cc [new file with mode: 0644]
src/xwalk/sysapps/raw_socket/udp_socket_object.h [new file with mode: 0644]
src/xwalk/sysapps/sysapps.gyp
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/NullContentsClient.java
src/xwalk/xwalk.gyp
src/xwalk/xwalk_tests.gypi

diff --git a/packaging/crosswalk-2.31-enable-VAVDA-with-EGL.patch b/packaging/crosswalk-2.31-enable-VAVDA-with-EGL.patch
deleted file mode 100644 (file)
index 6595561..0000000
+++ /dev/null
@@ -1,1313 +0,0 @@
-From c9f2fa16578bc20c83247e72608b5d6ca4dff6ba Mon Sep 17 00:00:00 2001
-From: "qing.zhang" <qing.zhang@intel.com>
-Date: Thu, 7 Nov 2013 08:59:38 -0500
-Subject: [PATCH] [Tizen] Enabling Hardware Acceleration with Libva and EGL in
-     VDA for Tizen Mobile within chromium v31+.
-
-Why we need to maintain it in our side:
-===========================================
-1) Upstream confirm VAVDA will continue to be restricted to
-   CrOS/X86 for dev & testing only and not for chromium road map.
-2) CrOS/X86 no plan to expend EGL backend which finalize in
-   June 2012 and be addressed to the CrOS graphics team.
-
-So, the upstream no plan to lerage VAVDA with EGL graphic
-   backend for any X86.
-
-3) The tizen-mobile's driver only support EGL as texture
-   backend. The video hw acceleration of xwalk have to
-   rely on EGL not GLX to bind decoded pixmap.
-===========================================
-That's why we enable specific EGL for VAVDA in tizen port.
----
- .../gpu/media/gpu_video_decode_accelerator.cc      |   8 +
- .../media/vaapi_video_decode_accelerator_tizen.cc  | 908 +++++++++++++++++++++
- .../media/vaapi_video_decode_accelerator_tizen.h   | 273 +++++++
- content/content_common.gypi                        |  26 +
- 4 files changed, 1215 insertions(+)
- create mode 100644 content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc
- create mode 100644 content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h
-
-diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc
-index bd1dc5f..c5a6df2 100644
---- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
-+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
-@@ -32,6 +32,8 @@
- #include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
- #include "ui/gl/gl_context_glx.h"
- #include "ui/gl/gl_implementation.h"
-+#elif defined(OS_TIZEN_MOBILE) && defined(ARCH_CPU_X86_FAMILY)
-+#include "content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h"
- #elif defined(OS_ANDROID)
- #include "content/common/gpu/media/android_video_decode_accelerator.h"
- #endif
-@@ -296,6 +298,12 @@ void GpuVideoDecodeAccelerator::Initialize(
-       static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext());
-   video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
-       glx_context->display(), this, make_context_current_));
-+#elif defined(OS_TIZEN_MOBILE) && defined(ARCH_CPU_X86_FAMILY)
-+  video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
-+      gfx::GLSurfaceEGL::GetHardwareDisplay(),
-+      stub_->decoder()->GetGLContext()->GetHandle(),
-+      this,
-+      make_context_current_));
- #elif defined(OS_ANDROID)
-   video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator(
-       this,
-diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc
-new file mode 100644
-index 0000000..cfff457
---- /dev/null
-+++ b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc
-@@ -0,0 +1,908 @@
-+// 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 "base/bind.h"
-+#include "base/debug/trace_event.h"
-+#include "base/logging.h"
-+#include "base/metrics/histogram.h"
-+#include "base/stl_util.h"
-+#include "base/strings/string_util.h"
-+#include "base/synchronization/waitable_event.h"
-+#include "content/child/child_thread.h"
-+#include "content/common/gpu/gpu_channel.h"
-+#include "content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h"
-+#include "media/base/bind_to_current_loop.h"
-+#include "media/video/picture.h"
-+#include "ui/gl/gl_bindings.h"
-+#include "ui/gl/scoped_binders.h"
-+
-+static void ReportToUMA(
-+    content::VaapiH264Decoder::VAVDAH264DecoderFailure failure) {
-+  UMA_HISTOGRAM_ENUMERATION(
-+      "Media.VAVDAH264.DecoderFailure",
-+      failure,
-+      content::VaapiH264Decoder::VAVDA_H264_DECODER_FAILURES_MAX);
-+}
-+
-+namespace content {
-+
-+#define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret)  \
-+  do {                                                              \
-+    if (!(result)) {                                                \
-+      DVLOG(1) << log;                                              \
-+      NotifyError(error_code);                                      \
-+      return ret;                                                   \
-+    }                                                               \
-+  } while (0)
-+
-+VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0), size(0) {
-+}
-+
-+VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {
-+}
-+
-+void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
-+  if (message_loop_ != base::MessageLoop::current()) {
-+    DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error));
-+    return;
-+  }
-+
-+  // Post Cleanup() as a task so we don't recursively acquire lock_.
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::Cleanup, weak_this_));
-+
-+  DVLOG(1) << "Notifying of error " << error;
-+  if (client_) {
-+    client_->NotifyError(error);
-+    client_ptr_factory_.InvalidateWeakPtrs();
-+  }
-+}
-+
-+// TFPPicture allocates X Pixmaps and binds them to textures passed
-+// in PictureBuffers from clients to them. TFPPictures are created as
-+// a consequence of receiving a set of PictureBuffers from clients and released
-+// at the end of decode (or when a new set of PictureBuffers is required).
-+//
-+// TFPPictures are used for output, contents of VASurfaces passed from decoder
-+// are put into the associated pixmap memory and sent to client.
-+class VaapiVideoDecodeAccelerator::TFPPicture {
-+ public:
-+  ~TFPPicture();
-+
-+  static linked_ptr<TFPPicture> Create(
-+      const base::Callback<bool(void)>& make_context_current,
-+      EGLDisplay egl_display,
-+      Display* x_display,
-+      int32 picture_buffer_id,
-+      uint32 texture_id,
-+      gfx::Size size);
-+  int32 picture_buffer_id() {
-+    return picture_buffer_id_;
-+  }
-+
-+  uint32 texture_id() {
-+    return texture_id_;
-+  }
-+
-+  gfx::Size size() {
-+    return size_;
-+  }
-+
-+  int x_pixmap() {
-+    return x_pixmap_;
-+  }
-+
-+  // Bind texture to pixmap. Needs to be called every frame.
-+  bool Bind();
-+
-+ private:
-+  TFPPicture(const base::Callback<bool(void)>& make_context_current,
-+             Display* x_display,
-+             int32 picture_buffer_id,
-+             uint32 texture_id,
-+             gfx::Size size);
-+
-+  bool Initialize(EGLDisplay egl_display);
-+
-+  base::Callback<bool(void)> make_context_current_;
-+
-+  Display* x_display_;
-+
-+  // Output id for the client.
-+  int32 picture_buffer_id_;
-+  uint32 texture_id_;
-+
-+  gfx::Size size_;
-+
-+  // Pixmaps bound to this texture.
-+  Pixmap x_pixmap_;
-+  EGLDisplay egl_display_;
-+  EGLImageKHR egl_image_;
-+
-+  DISALLOW_COPY_AND_ASSIGN(TFPPicture);
-+};
-+
-+VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
-+    const base::Callback<bool(void)>& make_context_current,
-+    Display* x_display,
-+    int32 picture_buffer_id,
-+    uint32 texture_id,
-+    gfx::Size size)
-+    : make_context_current_(make_context_current),
-+      x_display_(x_display),
-+      picture_buffer_id_(picture_buffer_id),
-+      texture_id_(texture_id),
-+      size_(size),
-+      x_pixmap_(0),
-+      egl_image_(0) {
-+  DCHECK(!make_context_current_.is_null());
-+};
-+
-+linked_ptr<VaapiVideoDecodeAccelerator::TFPPicture>
-+VaapiVideoDecodeAccelerator::TFPPicture::Create(
-+    const base::Callback<bool(void)>& make_context_current,
-+    EGLDisplay egl_display,
-+    Display* x_display,
-+    int32 picture_buffer_id,
-+    uint32 texture_id,
-+    gfx::Size size) {
-+
-+  linked_ptr<TFPPicture> tfp_picture(
-+    new TFPPicture(make_context_current, x_display,
-+                     picture_buffer_id, texture_id, size));
-+
-+  if (!tfp_picture->Initialize(egl_display))
-+    tfp_picture.reset();
-+
-+  return tfp_picture;
-+}
-+
-+bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
-+    EGLDisplay egl_display) {
-+  // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
-+  DCHECK(ChildThread::current() == NULL ||
-+      ChildThread::current()->message_loop() == base::MessageLoop::current());
-+
-+  if (!make_context_current_.Run())
-+    return false;
-+
-+  XWindowAttributes win_attr;
-+  int screen = DefaultScreen(x_display_);
-+  XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr);
-+  //TODO(posciak): pass the depth required by libva, not the RootWindow's depth
-+  x_pixmap_ = XCreatePixmap(x_display_, RootWindow(x_display_, screen),
-+                            size_.width(), size_.height(), win_attr.depth);
-+  if (!x_pixmap_) {
-+    DVLOG(1) << "Failed creating an X Pixmap for TFP";
-+    return false;
-+  }
-+
-+  egl_display_ = egl_display;
-+  EGLint image_attrs[] = { EGL_IMAGE_PRESERVED_KHR, 1 , EGL_NONE };
-+
-+  egl_image_ = eglCreateImageKHR(egl_display_,
-+                                EGL_NO_CONTEXT,
-+                                EGL_NATIVE_PIXMAP_KHR,
-+                                (EGLClientBuffer)x_pixmap_,
-+                                image_attrs);
-+  if (!egl_image_) {
-+    DVLOG(1) << "Failed creating a EGLImage from Pixmap for KHR";
-+    return false;
-+  }
-+
-+  return true;
-+}
-+VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
-+  // Check for NULL prevents unittests from crashing on non-existing ChildThread.
-+  DCHECK(ChildThread::current() == NULL ||
-+      ChildThread::current()->message_loop() == base::MessageLoop::current());
-+
-+  // Unbind surface from texture and deallocate resources.
-+  if (make_context_current_.Run()) {
-+      eglDestroyImageKHR(egl_display_, egl_image_);
-+  }
-+
-+  if (x_pixmap_)
-+    XFreePixmap(x_display_, x_pixmap_);
-+  XSync(x_display_, False);  // Needed to work around buggy vdpau-driver.
-+}
-+
-+bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
-+  DCHECK(x_pixmap_);
-+  DCHECK(egl_image_);
-+
-+  // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
-+  DCHECK(ChildThread::current() == NULL ||
-+      ChildThread::current()->message_loop() == base::MessageLoop::current());
-+
-+  if (!make_context_current_.Run())
-+    return false;
-+
-+  gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
-+  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
-+
-+  return true;
-+}
-+
-+VaapiVideoDecodeAccelerator::TFPPicture*
-+    VaapiVideoDecodeAccelerator::TFPPictureById(int32 picture_buffer_id) {
-+  TFPPictures::iterator it = tfp_pictures_.find(picture_buffer_id);
-+  if (it == tfp_pictures_.end()) {
-+    DVLOG(1) << "Picture id " << picture_buffer_id << " does not exist";
-+    return NULL;
-+  }
-+
-+  return it->second.get();
-+}
-+
-+VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
-+    EGLDisplay egl_display, EGLContext egl_context,
-+    Client* client,
-+    const base::Callback<bool(void)>& make_context_current)
-+    : x_display_(0),
-+      egl_display_(egl_display),
-+      egl_context_(egl_context),
-+      make_context_current_(make_context_current),
-+      state_(kUninitialized),
-+      input_ready_(&lock_),
-+      surfaces_available_(&lock_),
-+      message_loop_(base::MessageLoop::current()),
-+      weak_this_(base::AsWeakPtr(this)),
-+      client_ptr_factory_(client),
-+      client_(client_ptr_factory_.GetWeakPtr()),
-+      decoder_thread_("VaapiDecoderThread"),
-+      num_frames_at_client_(0),
-+      num_stream_bufs_at_decoder_(0),
-+      finish_flush_pending_(false),
-+      awaiting_va_surfaces_recycle_(false),
-+      requested_num_pics_(0) {
-+  DCHECK(client);
-+}
-+VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+}
-+
-+class ScopedPtrXFree {
-+ public:
-+  void operator()(void* x) const {
-+    ::XFree(x);
-+  }
-+};
-+
-+bool VaapiVideoDecodeAccelerator::Initialize(
-+    media::VideoCodecProfile profile) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  base::AutoLock auto_lock(lock_);
-+  DCHECK_EQ(state_, kUninitialized);
-+  DVLOG(2) << "Initializing VAVDA, profile: " << profile;
-+
-+  if (!make_context_current_.Run())
-+    return false;
-+
-+  x_display_ = base::MessagePumpForUI::GetDefaultXDisplay();
-+
-+  vaapi_wrapper_ = VaapiWrapper::Create(
-+      profile, x_display_,
-+      base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR));
-+
-+  if (!vaapi_wrapper_.get()) {
-+    DVLOG(1) << "Failed initializing VAAPI";
-+    return false;
-+  }
-+
-+  decoder_.reset(
-+      new VaapiH264Decoder(
-+          vaapi_wrapper_.get(),
-+          media::BindToCurrentLoop(base::Bind(
-+              &VaapiVideoDecodeAccelerator::SurfaceReady, weak_this_)),
-+          base::Bind(&ReportToUMA)));
-+
-+  CHECK(decoder_thread_.Start());
-+
-+  state_ = kIdle;
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyInitializeDone, client_));
-+  return true;
-+}
-+
-+void VaapiVideoDecodeAccelerator::SurfaceReady(
-+    int32 input_id,
-+    const scoped_refptr<VASurface>& va_surface) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DCHECK(!awaiting_va_surfaces_recycle_);
-+
-+  // Drop any requests to output if we are resetting or being destroyed.
-+  if (state_ == kResetting || state_ == kDestroying)
-+    return;
-+
-+  pending_output_cbs_.push(
-+      base::Bind(&VaapiVideoDecodeAccelerator::OutputPicture,
-+                 weak_this_, va_surface, input_id));
-+
-+  TryOutputSurface();
-+}
-+
-+void VaapiVideoDecodeAccelerator::OutputPicture(
-+    const scoped_refptr<VASurface>& va_surface,
-+    int32 input_id,
-+    TFPPicture* tfp_picture) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  int32 output_id  = tfp_picture->picture_buffer_id();
-+
-+  TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface",
-+               "input_id", input_id,
-+               "output_id", output_id);
-+
-+  DVLOG(3) << "Outputting VASurface " << va_surface->id()
-+           << " into pixmap bound to picture buffer id " << output_id;
-+
-+  RETURN_AND_NOTIFY_ON_FAILURE(tfp_picture->Bind(),
-+                               "Failed binding texture to pixmap",
-+                               PLATFORM_FAILURE, );
-+
-+  RETURN_AND_NOTIFY_ON_FAILURE(
-+      vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface->id(),
-+                                           tfp_picture->x_pixmap(),
-+                                           tfp_picture->size()),
-+      "Failed putting surface into pixmap", PLATFORM_FAILURE, );
-+
-+  // Notify the client a picture is ready to be displayed.
-+  ++num_frames_at_client_;
-+  TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
-+  DVLOG(4) << "Notifying output picture id " << output_id
-+           << " for input "<< input_id << " is ready";
-+  client_->PictureReady(media::Picture(output_id, input_id));
-+}
-+
-+void VaapiVideoDecodeAccelerator::TryOutputSurface() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  // Handle Destroy() arriving while pictures are queued for output.
-+  if (!client_)
-+    return;
-+
-+  if (pending_output_cbs_.empty() || output_buffers_.empty())
-+    return;
-+
-+  OutputCB output_cb = pending_output_cbs_.front();
-+  pending_output_cbs_.pop();
-+
-+  TFPPicture* tfp_picture = TFPPictureById(output_buffers_.front());
-+  DCHECK(tfp_picture);
-+  output_buffers_.pop();
-+
-+  output_cb.Run(tfp_picture);
-+
-+  if (finish_flush_pending_ && pending_output_cbs_.empty())
-+    FinishFlush();
-+}
-+
-+void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
-+    const media::BitstreamBuffer& bitstream_buffer) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id",
-+      bitstream_buffer.id());
-+
-+  DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id()
-+           << " size: " << (int)bitstream_buffer.size();
-+
-+  scoped_ptr<base::SharedMemory> shm(
-+      new base::SharedMemory(bitstream_buffer.handle(), true));
-+  RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(bitstream_buffer.size()),
-+                              "Failed to map input buffer", UNREADABLE_INPUT,);
-+
-+  base::AutoLock auto_lock(lock_);
-+
-+  // Set up a new input buffer and queue it for later.
-+  linked_ptr<InputBuffer> input_buffer(new InputBuffer());
-+  input_buffer->shm.reset(shm.release());
-+  input_buffer->id = bitstream_buffer.id();
-+  input_buffer->size = bitstream_buffer.size();
-+
-+  ++num_stream_bufs_at_decoder_;
-+  TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
-+                 num_stream_bufs_at_decoder_);
-+
-+  input_buffers_.push(input_buffer);
-+  input_ready_.Signal();
-+}
-+
-+bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  lock_.AssertAcquired();
-+
-+  if (curr_input_buffer_.get())
-+    return true;
-+
-+  // Will only wait if it is expected that in current state new buffers will
-+  // be queued from the client via Decode(). The state can change during wait.
-+  while (input_buffers_.empty() && (state_ == kDecoding || state_ == kIdle)) {
-+    input_ready_.Wait();
-+  }
-+
-+  // We could have got woken up in a different state or never got to sleep
-+  // due to current state; check for that.
-+  switch (state_) {
-+    case kFlushing:
-+      // Here we are only interested in finishing up decoding buffers that are
-+      // already queued up. Otherwise will stop decoding.
-+      if (input_buffers_.empty())
-+        return false;
-+      // else fallthrough
-+    case kDecoding:
-+    case kIdle:
-+      DCHECK(!input_buffers_.empty());
-+
-+      curr_input_buffer_ = input_buffers_.front();
-+      input_buffers_.pop();
-+
-+      DVLOG(4) << "New current bitstream buffer, id: "
-+               << curr_input_buffer_->id
-+               << " size: " << curr_input_buffer_->size;
-+
-+      decoder_->SetStream(
-+          static_cast<uint8*>(curr_input_buffer_->shm->memory()),
-+          curr_input_buffer_->size, curr_input_buffer_->id);
-+      return true;
-+
-+    default:
-+      // We got woken up due to being destroyed/reset, ignore any already
-+      // queued inputs.
-+      return false;
-+  }
-+}
-+
-+void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
-+  lock_.AssertAcquired();
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  DCHECK(curr_input_buffer_.get());
-+
-+  int32 id = curr_input_buffer_->id;
-+  curr_input_buffer_.reset();
-+  DVLOG(4) << "End of input buffer " << id;
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyEndOfBitstreamBuffer, client_, id));
-+
-+  --num_stream_bufs_at_decoder_;
-+  TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
-+                 num_stream_bufs_at_decoder_);
-+}
-+
-+bool VaapiVideoDecodeAccelerator::FeedDecoderWithOutputSurfaces_Locked() {
-+  lock_.AssertAcquired();
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+
-+  while (available_va_surfaces_.empty() &&
-+         (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) {
-+    surfaces_available_.Wait();
-+  }
-+
-+  if (state_ != kDecoding && state_ != kFlushing && state_ != kIdle)
-+    return false;
-+
-+  VASurface::ReleaseCB va_surface_release_cb =
-+      media::BindToCurrentLoop(base::Bind(
-+          &VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_));
-+
-+  while (!available_va_surfaces_.empty()) {
-+    scoped_refptr<VASurface> va_surface(
-+        new VASurface(available_va_surfaces_.front(), va_surface_release_cb));
-+    available_va_surfaces_.pop_front();
-+    decoder_->ReuseSurface(va_surface);
-+  }
-+
-+  return true;
-+}
-+
-+void VaapiVideoDecodeAccelerator::DecodeTask() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask");
-+  base::AutoLock auto_lock(lock_);
-+
-+  if (state_ != kDecoding)
-+    return;
-+
-+  // Main decode task.
-+  DVLOG(4) << "Decode task";
-+
-+  // Try to decode what stream data is (still) in the decoder until we run out
-+  // of it.
-+  while (GetInputBuffer_Locked()) {
-+    DCHECK(curr_input_buffer_.get());
-+
-+    VaapiH264Decoder::DecResult res;
-+    {
-+      // We are OK releasing the lock here, as decoder never calls our methods
-+      // directly and we will reacquire the lock before looking at state again.
-+      // This is the main decode function of the decoder and while keeping
-+      // the lock for its duration would be fine, it would defeat the purpose
-+      // of having a separate decoder thread.
-+      base::AutoUnlock auto_unlock(lock_);
-+      res = decoder_->Decode();
-+    }
-+
-+    switch (res) {
-+      case VaapiH264Decoder::kAllocateNewSurfaces:
-+        DVLOG(1) << "Decoder requesting a new set of surfaces";
-+        message_loop_->PostTask(FROM_HERE, base::Bind(
-+            &VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, weak_this_,
-+                decoder_->GetRequiredNumOfPictures(),
-+                decoder_->GetPicSize()));
-+        // We'll get rescheduled once ProvidePictureBuffers() finishes.
-+        return;
-+
-+      case VaapiH264Decoder::kRanOutOfStreamData:
-+        ReturnCurrInputBuffer_Locked();
-+        break;
-+
-+      case VaapiH264Decoder::kRanOutOfSurfaces:
-+        // No more output buffers in the decoder, try getting more or go to
-+        // sleep waiting for them.
-+        if (!FeedDecoderWithOutputSurfaces_Locked())
-+          return;
-+
-+        break;
-+
-+      case VaapiH264Decoder::kDecodeError:
-+        RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream",
-+                                     PLATFORM_FAILURE, );
-+        return;
-+    }
-+  }
-+}
-+
-+void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(size_t num_pics,
-+                                                           gfx::Size size) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DCHECK(!awaiting_va_surfaces_recycle_);
-+
-+  // At this point decoder has stopped running and has already posted onto our
-+  // loop any remaining output request callbacks, which executed before we got
-+  // here. Some of them might have been pended though, because we might not
-+  // have had enough TFPictures to output surfaces to. Initiate a wait cycle,
-+  // which will wait for client to return enough PictureBuffers to us, so that
-+  // we can finish all pending output callbacks, releasing associated surfaces.
-+  DVLOG(1) << "Initiating surface set change";
-+  awaiting_va_surfaces_recycle_ = true;
-+
-+  requested_num_pics_ = num_pics;
-+  requested_pic_size_ = size;
-+
-+  TryFinishSurfaceSetChange();
-+}
-+
-+void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  if (!awaiting_va_surfaces_recycle_)
-+    return;
-+
-+  if (!pending_output_cbs_.empty() ||
-+      tfp_pictures_.size() != available_va_surfaces_.size()) {
-+    // Either:
-+    // 1. Not all pending pending output callbacks have been executed yet.
-+    // Wait for the client to return enough pictures and retry later.
-+    // 2. The above happened and all surface release callbacks have been posted
-+    // as the result, but not all have executed yet. Post ourselves after them
-+    // to let them release surfaces.
-+    DVLOG(2) << "Awaiting pending output/surface release callbacks to finish";
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, weak_this_));
-+    return;
-+  }
-+
-+  // All surfaces released, destroy them and dismiss all PictureBuffers.
-+  awaiting_va_surfaces_recycle_ = false;
-+  available_va_surfaces_.clear();
-+  vaapi_wrapper_->DestroySurfaces();
-+
-+  for (TFPPictures::iterator iter = tfp_pictures_.begin();
-+       iter != tfp_pictures_.end(); ++iter) {
-+    DVLOG(2) << "Dismissing picture id: " << iter->first;
-+    client_->DismissPictureBuffer(iter->first);
-+  }
-+  tfp_pictures_.clear();
-+
-+  // And ask for a new set as requested.
-+  DVLOG(1) << "Requesting " << requested_num_pics_ << " pictures of size: "
-+           << requested_pic_size_.ToString();
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::ProvidePictureBuffers, client_,
-+      requested_num_pics_, requested_pic_size_, GL_TEXTURE_2D));
-+}
-+
-+void VaapiVideoDecodeAccelerator::Decode(
-+    const media::BitstreamBuffer& bitstream_buffer) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id",
-+               bitstream_buffer.id());
-+
-+  // We got a new input buffer from the client, map it and queue for later use.
-+  MapAndQueueNewInputBuffer(bitstream_buffer);
-+
-+  base::AutoLock auto_lock(lock_);
-+  switch (state_) {
-+    case kIdle:
-+      state_ = kDecoding;
-+      decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+          &VaapiVideoDecodeAccelerator::DecodeTask,
-+          base::Unretained(this)));
-+      break;
-+
-+    case kDecoding:
-+      // Decoder already running.
-+    case kResetting:
-+      // When resetting, allow accumulating bitstream buffers, so that
-+      // the client can queue after-seek-buffers while we are finishing with
-+      // the before-seek one.
-+      break;
-+
-+    default:
-+      RETURN_AND_NOTIFY_ON_FAILURE(false,
-+          "Decode request from client in invalid state: " << state_,
-+          PLATFORM_FAILURE, );
-+      break;
-+  }
-+}
-+
-+void VaapiVideoDecodeAccelerator::RecycleVASurfaceID(
-+    VASurfaceID va_surface_id) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  base::AutoLock auto_lock(lock_);
-+
-+  available_va_surfaces_.push_back(va_surface_id);
-+  surfaces_available_.Signal();
-+}
-+
-+void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
-+    const std::vector<media::PictureBuffer>& buffers) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  base::AutoLock auto_lock(lock_);
-+  DCHECK(tfp_pictures_.empty());
-+
-+  while (!output_buffers_.empty())
-+    output_buffers_.pop();
-+
-+  RETURN_AND_NOTIFY_ON_FAILURE(
-+      buffers.size() == requested_num_pics_,
-+      "Got an invalid number of picture buffers. (Got " << buffers.size()
-+      << ", requested " << requested_num_pics_ << ")", INVALID_ARGUMENT, );
-+  DCHECK(requested_pic_size_ == buffers[0].size());
-+
-+  std::vector<VASurfaceID> va_surface_ids;
-+  RETURN_AND_NOTIFY_ON_FAILURE(
-+      vaapi_wrapper_->CreateSurfaces(requested_pic_size_,
-+                                     buffers.size(),
-+                                     &va_surface_ids),
-+      "Failed creating VA Surfaces", PLATFORM_FAILURE, );
-+  DCHECK_EQ(va_surface_ids.size(), buffers.size());
-+
-+  for (size_t i = 0; i < buffers.size(); ++i) {
-+    DVLOG(2) << "Assigning picture id: " << buffers[i].id()
-+             << " to texture id: " << buffers[i].texture_id()
-+             << " VASurfaceID: " << va_surface_ids[i];
-+
-+    linked_ptr<TFPPicture> tfp_picture(
-+        TFPPicture::Create(make_context_current_, egl_display_, x_display_,
-+                           buffers[i].id(), buffers[i].texture_id(),
-+                           requested_pic_size_));
-+
-+    RETURN_AND_NOTIFY_ON_FAILURE(
-+        tfp_picture.get(), "Failed assigning picture buffer to a texture.",
-+        PLATFORM_FAILURE, );
-+
-+    bool inserted = tfp_pictures_.insert(std::make_pair(
-+        buffers[i].id(), tfp_picture)).second;
-+    DCHECK(inserted);
-+
-+    output_buffers_.push(buffers[i].id());
-+    available_va_surfaces_.push_back(va_surface_ids[i]);
-+    surfaces_available_.Signal();
-+  }
-+
-+  state_ = kDecoding;
-+  decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::DecodeTask, base::Unretained(this)));
-+}
-+
-+void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id",
-+               picture_buffer_id);
-+
-+  --num_frames_at_client_;
-+  TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
-+
-+  output_buffers_.push(picture_buffer_id);
-+  TryOutputSurface();
-+}
-+
-+void VaapiVideoDecodeAccelerator::FlushTask() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  DVLOG(1) << "Flush task";
-+
-+  // First flush all the pictures that haven't been outputted, notifying the
-+  // client to output them.
-+  bool res = decoder_->Flush();
-+  RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.",
-+                               PLATFORM_FAILURE, );
-+
-+  // Put the decoder in idle state, ready to resume.
-+  decoder_->Reset();
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_));
-+}
-+
-+void VaapiVideoDecodeAccelerator::Flush() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DVLOG(1) << "Got flush request";
-+
-+  base::AutoLock auto_lock(lock_);
-+  state_ = kFlushing;
-+  // Queue a flush task after all existing decoding tasks to clean up.
-+  decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
-+
-+  input_ready_.Signal();
-+  surfaces_available_.Signal();
-+}
-+
-+void VaapiVideoDecodeAccelerator::FinishFlush() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  finish_flush_pending_ = false;
-+
-+  base::AutoLock auto_lock(lock_);
-+  if (state_ != kFlushing) {
-+    DCHECK_EQ(state_, kDestroying);
-+    return;  // We could've gotten destroyed already.
-+  }
-+
-+  // Still waiting for textures from client to finish outputting all pending
-+  // frames. Try again later.
-+  if (!pending_output_cbs_.empty()) {
-+    finish_flush_pending_ = true;
-+    return;
-+  }
-+
-+  state_ = kIdle;
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyFlushDone, client_));
-+
-+  DVLOG(1) << "Flush finished";
-+}
-+
-+void VaapiVideoDecodeAccelerator::ResetTask() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  DVLOG(1) << "ResetTask";
-+
-+  // All the decoding tasks from before the reset request from client are done
-+  // by now, as this task was scheduled after them and client is expected not
-+  // to call Decode() after Reset() and before NotifyResetDone.
-+  decoder_->Reset();
-+
-+  base::AutoLock auto_lock(lock_);
-+
-+  // Return current input buffer, if present.
-+  if (curr_input_buffer_.get())
-+    ReturnCurrInputBuffer_Locked();
-+
-+  // And let client know that we are done with reset.
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
-+}
-+
-+void VaapiVideoDecodeAccelerator::Reset() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DVLOG(1) << "Got reset request";
-+
-+  // This will make any new decode tasks exit early.
-+  base::AutoLock auto_lock(lock_);
-+  state_ = kResetting;
-+  finish_flush_pending_ = false;
-+
-+  // Drop all remaining input buffers, if present.
-+  while (!input_buffers_.empty()) {
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &Client::NotifyEndOfBitstreamBuffer, client_,
-+        input_buffers_.front()->id));
-+    input_buffers_.pop();
-+  }
-+
-+  decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
-+
-+  input_ready_.Signal();
-+  surfaces_available_.Signal();
-+}
-+
-+void VaapiVideoDecodeAccelerator::FinishReset() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DVLOG(1) << "FinishReset";
-+  base::AutoLock auto_lock(lock_);
-+
-+  if (state_ != kResetting) {
-+    DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_;
-+    return;  // We could've gotten destroyed already.
-+  }
-+
-+  // Drop pending outputs.
-+  while (!pending_output_cbs_.empty())
-+    pending_output_cbs_.pop();
-+
-+  if (awaiting_va_surfaces_recycle_) {
-+    // Decoder requested a new surface set while we were waiting for it to
-+    // finish the last DecodeTask, running at the time of Reset().
-+    // Let the surface set change finish first before resetting.
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
-+    return;
-+  }
-+
-+  num_stream_bufs_at_decoder_ = 0;
-+  state_ = kIdle;
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyResetDone, client_));
-+
-+  // The client might have given us new buffers via Decode() while we were
-+  // resetting and might be waiting for our move, and not call Decode() anymore
-+  // until we return something. Post a DecodeTask() so that we won't
-+  // sleep forever waiting for Decode() in that case. Having two of them
-+  // in the pipe is harmless, the additional one will return as soon as it sees
-+  // that we are back in kDecoding state.
-+  if (!input_buffers_.empty()) {
-+    state_ = kDecoding;
-+    decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::DecodeTask,
-+      base::Unretained(this)));
-+  }
-+
-+  DVLOG(1) << "Reset finished";
-+}
-+
-+void VaapiVideoDecodeAccelerator::Cleanup() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  if (state_ == kUninitialized || state_ == kDestroying)
-+    return;
-+
-+  DVLOG(1) << "Destroying VAVDA";
-+  base::AutoLock auto_lock(lock_);
-+  state_ = kDestroying;
-+
-+  client_ptr_factory_.InvalidateWeakPtrs();
-+
-+  {
-+    base::AutoUnlock auto_unlock(lock_);
-+    // Post a dummy task to the decoder_thread_ to ensure it is drained.
-+    base::WaitableEvent waiter(false, false);
-+    decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+        &base::WaitableEvent::Signal, base::Unretained(&waiter)));
-+    input_ready_.Signal();
-+    surfaces_available_.Signal();
-+    waiter.Wait();
-+    decoder_thread_.Stop();
-+  }
-+
-+  state_ = kUninitialized;
-+}
-+
-+void VaapiVideoDecodeAccelerator::Destroy() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  Cleanup();
-+  delete this;
-+}
-+
-+}  // namespace content
-diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h
-new file mode 100644
-index 0000000..d41cf38
---- /dev/null
-+++ b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h
-@@ -0,0 +1,273 @@
-+// 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.
-+//
-+// This file contains an implementation of VideoDecoderAccelerator
-+// that utilizes hardware video decoder present on Intel CPUs for Tizen.
-+
-+#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
-+#define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
-+
-+#include <map>
-+#include <queue>
-+#include <utility>
-+#include <vector>
-+
-+#include "base/logging.h"
-+#include "base/memory/linked_ptr.h"
-+#include "base/memory/shared_memory.h"
-+#include "base/memory/weak_ptr.h"
-+#include "base/message_loop/message_loop.h"
-+#include "base/synchronization/condition_variable.h"
-+#include "base/synchronization/lock.h"
-+#include "base/threading/non_thread_safe.h"
-+#include "base/threading/thread.h"
-+#include "content/common/content_export.h"
-+#include "content/common/gpu/media/vaapi_h264_decoder.h"
-+#include "content/common/gpu/media/vaapi_wrapper.h"
-+#include "content/common/gpu/media/video_decode_accelerator_impl.h"
-+#include "media/base/bitstream_buffer.h"
-+#include "media/video/picture.h"
-+#include "media/video/video_decode_accelerator.h"
-+#include "ui/gl/gl_bindings.h"
-+
-+namespace content {
-+
-+// Class to provide video decode acceleration for Intel systems with hardware
-+// support for it, and on which libva is available.
-+// Decoding tasks are performed in a separate decoding thread.
-+//
-+// Threading/life-cycle: this object is created & destroyed on the GPU
-+// ChildThread.  A few methods on it are called on the decoder thread which is
-+// stopped during |this->Destroy()|, so any tasks posted to the decoder thread
-+// can assume |*this| is still alive.  See |weak_this_| below for more details.
-+class CONTENT_EXPORT VaapiVideoDecodeAccelerator
-+    : public VideoDecodeAcceleratorImpl {
-+ public:
-+  VaapiVideoDecodeAccelerator(
-+      EGLDisplay egl_display, EGLContext egl_context,
-+      Client* client,
-+      const base::Callback<bool(void)>& make_context_current);
-+  virtual ~VaapiVideoDecodeAccelerator();
-+
-+  // media::VideoDecodeAccelerator implementation.
-+  virtual bool Initialize(media::VideoCodecProfile profile) OVERRIDE;
-+  virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
-+  virtual void AssignPictureBuffers(
-+      const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
-+  virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
-+  virtual void Flush() OVERRIDE;
-+  virtual void Reset() OVERRIDE;
-+  virtual void Destroy() OVERRIDE;
-+
-+private:
-+  // Notify the client that |output_id| is ready for displaying.
-+  void NotifyPictureReady(int32 input_id, int32 output_id);
-+
-+  // Notify the client that an error has occurred and decoding cannot continue.
-+  void NotifyError(Error error);
-+
-+  // Map the received input buffer into this process' address space and
-+  // queue it for decode.
-+  void MapAndQueueNewInputBuffer(
-+      const media::BitstreamBuffer& bitstream_buffer);
-+
-+  // Get a new input buffer from the queue and set it up in decoder. This will
-+  // sleep if no input buffers are available. Return true if a new buffer has
-+  // been set up, false if an early exit has been requested (due to initiated
-+  // reset/flush/destroy).
-+  bool GetInputBuffer_Locked();
-+
-+  // Signal the client that the current buffer has been read and can be
-+  // returned. Will also release the mapping.
-+  void ReturnCurrInputBuffer_Locked();
-+
-+  // Pass one or more output buffers to the decoder. This will sleep
-+  // if no buffers are available. Return true if buffers have been set up or
-+  // false if an early exit has been requested (due to initiated
-+  // reset/flush/destroy).
-+  bool FeedDecoderWithOutputSurfaces_Locked();
-+
-+  // Continue decoding given input buffers and sleep waiting for input/output
-+  // as needed. Will exit if a new set of surfaces or reset/flush/destroy
-+  // is requested.
-+  void DecodeTask();
-+
-+  // Scheduled after receiving a flush request and executed after the current
-+  // decoding task finishes decoding pending inputs. Makes the decoder return
-+  // all remaining output pictures and puts it in an idle state, ready
-+  // to resume if needed and schedules a FinishFlush.
-+  void FlushTask();
-+
-+  // Scheduled by the FlushTask after decoder is flushed to put VAVDA into idle
-+  // state and notify the client that flushing has been finished.
-+  void FinishFlush();
-+
-+  // Scheduled after receiving a reset request and executed after the current
-+  // decoding task finishes decoding the current frame. Puts the decoder into
-+  // an idle state, ready to resume if needed, discarding decoded but not yet
-+  // outputted pictures (decoder keeps ownership of their associated picture
-+  // buffers). Schedules a FinishReset afterwards.
-+  void ResetTask();
-+
-+  // Scheduled by ResetTask after it's done putting VAVDA into an idle state.
-+  // Drops remaining input buffers and notifies the client that reset has been
-+  // finished.
-+  void FinishReset();
-+
-+  // Helper for Destroy(), doing all the actual work except for deleting self.
-+  void Cleanup();
-+
-+  // Get a usable framebuffer configuration for use in binding textures
-+  // or return false on failure.
-+  bool InitializeFBConfig();
-+
-+  // Callback for the decoder to execute when it wants us to output given
-+  // |va_surface|.
-+  void SurfaceReady(int32 input_id, const scoped_refptr<VASurface>& va_surface);
-+
-+  // Represents a texture bound to an X Pixmap for output purposes.
-+  class TFPPicture;
-+
-+  // Callback to be executed once we have a |va_surface| to be output and
-+  // an available |tfp_picture| to use for output.
-+  // Puts contents of |va_surface| into given |tfp_picture|, releases the
-+  // surface and passes the resulting picture to client for output.
-+  void OutputPicture(const scoped_refptr<VASurface>& va_surface,
-+                     int32 input_id,
-+                     TFPPicture* tfp_picture);
-+
-+  // Try to OutputPicture() if we have both a ready surface and picture.
-+  void TryOutputSurface();
-+
-+  // Called when a VASurface is no longer in use by the decoder or is not being
-+  // synced/waiting to be synced to a picture. Returns it to available surfaces
-+  // pool.
-+  void RecycleVASurfaceID(VASurfaceID va_surface_id);
-+
-+  // Initiate wait cycle for surfaces to be released before we release them
-+  // and allocate new ones, as requested by the decoder.
-+  void InitiateSurfaceSetChange(size_t num_pics, gfx::Size size);
-+  // Check if the surfaces have been released or post ourselves for later.
-+  void TryFinishSurfaceSetChange();
-+
-+  // Client-provided X/EGL state.
-+  Display* x_display_;
-+  EGLDisplay egl_display_;
-+  EGLContext egl_context_;
-+  base::Callback<bool(void)> make_context_current_;
-+
-+  // VAVDA state.
-+  enum State {
-+    // Initialize() not called yet or failed.
-+    kUninitialized,
-+    // DecodeTask running.
-+    kDecoding,
-+    // Resetting, waiting for decoder to finish current task and cleanup.
-+    kResetting,
-+    // Flushing, waiting for decoder to finish current task and cleanup.
-+    kFlushing,
-+    // Idle, decoder in state ready to start/resume decoding.
-+    kIdle,
-+    // Destroying, waiting for the decoder to finish current task.
-+    kDestroying,
-+  };
-+
-+  // Protects input buffer and surface queues and state_.
-+  base::Lock lock_;
-+  State state_;
-+
-+  // An input buffer awaiting consumption, provided by the client.
-+  struct InputBuffer {
-+    InputBuffer();
-+    ~InputBuffer();
-+
-+    int32 id;
-+    size_t size;
-+    scoped_ptr<base::SharedMemory> shm;
-+  };
-+
-+  // Queue for incoming input buffers.
-+  typedef std::queue<linked_ptr<InputBuffer> > InputBuffers;
-+  InputBuffers input_buffers_;
-+  // Signalled when input buffers are queued onto the input_buffers_ queue.
-+  base::ConditionVariable input_ready_;
-+
-+  // Current input buffer at decoder.
-+  linked_ptr<InputBuffer> curr_input_buffer_;
-+
-+  // Queue for incoming output buffers (texture ids).
-+  typedef std::queue<int32> OutputBuffers;
-+  OutputBuffers output_buffers_;
-+
-+  typedef std::map<int32, linked_ptr<TFPPicture> > TFPPictures;
-+  // All allocated TFPPictures, regardless of their current state. TFPPictures
-+  // are allocated once and destroyed at the end of decode.
-+  TFPPictures tfp_pictures_;
-+
-+  // Return a TFPPicture associated with given client-provided id.
-+  TFPPicture* TFPPictureById(int32 picture_buffer_id);
-+
-+  // VA Surfaces no longer in use that can be passed back to the decoder for
-+  // reuse, once it requests them.
-+  std::list<VASurfaceID> available_va_surfaces_;
-+  // Signalled when output surfaces are queued onto the available_va_surfaces_
-+  // queue.
-+  base::ConditionVariable surfaces_available_;
-+
-+  // Pending output requests from the decoder. When it indicates that we should
-+  // output a surface and we have an available TFPPicture (i.e. texture) ready
-+  // to use, we'll execute the callback passing the TFPPicture. The callback
-+  // will put the contents of the surface into the picture and return it to
-+  // the client, releasing the surface as well.
-+  // If we don't have any available TFPPictures at the time when the decoder
-+  // requests output, we'll store the request on pending_output_cbs_ queue for
-+  // later and run it once the client gives us more textures
-+  // via ReusePictureBuffer().
-+  typedef base::Callback<void(TFPPicture*)> OutputCB;
-+  std::queue<OutputCB> pending_output_cbs_;
-+
-+  // ChildThread's message loop
-+  base::MessageLoop* message_loop_;
-+
-+  // WeakPtr<> pointing to |this| for use in posting tasks from the decoder
-+  // thread back to the ChildThread.  Because the decoder thread is a member of
-+  // this class, any task running on the decoder thread is guaranteed that this
-+  // object is still alive.  As a result, tasks posted from ChildThread to
-+  // decoder thread should use base::Unretained(this), and tasks posted from the
-+  // decoder thread to the ChildThread should use |weak_this_|.
-+  base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_;
-+
-+  // To expose client callbacks from VideoDecodeAccelerator.
-+  // NOTE: all calls to these objects *MUST* be executed on message_loop_.
-+  base::WeakPtrFactory<Client> client_ptr_factory_;
-+  base::WeakPtr<Client> client_;
-+
-+  scoped_ptr<VaapiWrapper> vaapi_wrapper_;
-+
-+  // Comes after vaapi_wrapper_ to ensure its destructor is executed before
-+  // vaapi_wrapper_ is destroyed.
-+  scoped_ptr<VaapiH264Decoder> decoder_;
-+  base::Thread decoder_thread_;
-+
-+  int num_frames_at_client_;
-+  int num_stream_bufs_at_decoder_;
-+
-+  // Whether we are waiting for any pending_output_cbs_ to be run before
-+  // NotifyingFlushDone.
-+  bool finish_flush_pending_;
-+
-+  // Decoder requested a new surface set and we are waiting for all the surfaces
-+  // to be returned before we can free them.
-+  bool awaiting_va_surfaces_recycle_;
-+
-+  // Last requested number/resolution of output picture buffers.
-+  size_t requested_num_pics_;
-+  gfx::Size requested_pic_size_;
-+
-+  DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator);
-+};
-+
-+}  // namespace content
-+
-+#endif  // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
-diff --git a/content/content_common.gypi b/content/content_common.gypi
-index 9d6cb61..3f53dd5 100644
---- a/content/content_common.gypi
-+++ b/content/content_common.gypi
-@@ -583,6 +583,32 @@
-         '<(DEPTH)/third_party/libva',
-       ],
-     }],
-+    ['target_arch != "arm" and tizen_mobile == 1 and use_x11 == 1', {
-+      'dependencies': [
-+        '../media/media.gyp:media',
-+      ],
-+      'sources': [
-+        'common/gpu/media/h264_dpb.cc',
-+        'common/gpu/media/h264_dpb.h',
-+        'common/gpu/media/va_surface.h',
-+        'common/gpu/media/vaapi_h264_decoder.cc',
-+        'common/gpu/media/vaapi_h264_decoder.h',
-+        'common/gpu/media/vaapi_video_decode_accelerator_tizen.cc',
-+        'common/gpu/media/vaapi_video_decode_accelerator_tizen.h',
-+        'common/gpu/media/vaapi_wrapper.cc',
-+        'common/gpu/media/vaapi_wrapper.h',
-+      ],
-+      'include_dirs': [
-+        '<(DEPTH)/third_party/libva',
-+        '<(DEPTH)/third_party/khronos',
-+      ],
-+      'link_settings': {
-+        'libraries': [
-+          '-lEGL',
-+          '-lGLESv2',
-+        ],
-+      },
-+    }],
-     ['OS=="win"', {
-       'dependencies': [
-         '../media/media.gyp:media',
-diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
-index 9e29e03..2c04d40 100644
---- a/content/gpu/gpu_main.cc
-+++ b/content/gpu/gpu_main.cc
-@@ -42,7 +42,8 @@
- #include "sandbox/win/src/sandbox.h"
- #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
- #include "content/common/gpu/media/exynos_video_decode_accelerator.h"
--#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
-+#elif (defined(OS_CHROMEOS) || defined(OS_TIZEN_MOBILE)) &&\
-+ defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
- #include "content/common/gpu/media/vaapi_wrapper.h"
- #endif
-@@ -360,7 +361,8 @@ bool WarmUpSandbox(const CommandLine& command_line) {
- #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
-   ExynosVideoDecodeAccelerator::PreSandboxInitialization();
--#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
-+#elif (defined(OS_CHROMEOS) || defined(OS_TIZEN_MOBILE)) &&\
-+ defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
-   VaapiWrapper::PreSandboxInitialization();
- #endif
--- 
-1.8.3.2
-
index 3e2ed89..5a327fd 100644 (file)
@@ -2,7 +2,7 @@
 %bcond_with wayland
 
 Name:           crosswalk
-Version:        5.34.105.0
+Version:        6.34.113.0
 Release:        0
 Summary:        Crosswalk is an app runtime based on Chromium
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -16,7 +16,6 @@ Source1001:     crosswalk.manifest
 Source1002:     %{name}.xml.in
 Source1003:     %{name}.png
 Patch1:         %{name}-do-not-look-for-gtk2-when-using-aura.patch
-Patch7:         %{name}-tizen-audio-session-manager.patch
 Patch8:         %{name}-mesa-ozone-typedefs.patch
 Patch9:         Blink-Add-GCC-flag-Wno-narrowing-fix-64bits-build.patch
 
@@ -26,13 +25,13 @@ BuildRequires:  expat-devel
 BuildRequires:  flex
 BuildRequires:  gperf
 BuildRequires:  libcap-devel
+BuildRequires:  ninja
 BuildRequires:  python
 BuildRequires:  python-xml
 BuildRequires:  perl
 BuildRequires:  which
 BuildRequires:  pkgconfig(alsa)
 BuildRequires:  pkgconfig(appcore-common)
-BuildRequires:  pkgconfig(audio-session-mgr)
 BuildRequires:  pkgconfig(cairo)
 BuildRequires:  pkgconfig(capi-location-manager)
 BuildRequires:  pkgconfig(dbus-1)
@@ -107,7 +106,6 @@ cp -a src/LICENSE LICENSE.chromium
 cp -a src/xwalk/LICENSE LICENSE.xwalk
 
 %patch1
-%patch7
 
 %if "%{tizen}" < "3.0"
 %patch2
@@ -143,34 +141,20 @@ export LDFLAGS="${LDFLAGS} -Wl,--no-keep-memory"
 # build root to the BUILDDIR_NAME definition, such as "/var/tmp/xwalk-build"
 # (remember all paths are still inside the chroot):
 #    gbs build --define 'BUILDDIR_NAME /some/path'
-#
-# The --depth and --generator-output combo is used to put all the Makefiles
-# inside the build directory, and (this is the important part) keep file lists
-# (generatedwith <|() in gyp) in the build directory as well, otherwise they
-# will be in the source directory, erased every time and trigger an almost full
-# Blink rebuild (among other smaller targets).
-# We cannot always pass those flags, though, because gyp's make generator does
-# not work if the --generator-output is the top-level source directory.
 BUILDDIR_NAME="%{?BUILDDIR_NAME}"
-if [ -z "${BUILDDIR_NAME}" ]; then
-   BUILDDIR_NAME="."
-else
-   GYP_EXTRA_FLAGS="--depth=. --generator-output=${BUILDDIR_NAME}"
+if [ -n "${BUILDDIR_NAME}" ]; then
+   mkdir -p "${BUILDDIR_NAME}"
+   ln -s "${BUILDDIR_NAME}" src/out
 fi
 
 %if %{with wayland}
-GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ash=1 -Duse_ozone=1"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1"
 %endif
 
-# Change src/ so that we can pass "." to --depth below, otherwise we would need
-# to pass "src" to it, but this confuses the gyp make generator, that expects
-# to be called from the root source directory.
-cd src
-
 # --no-parallel is added because chroot does not mount a /dev/shm, this will
 # cause python multiprocessing.SemLock error.
-export GYP_GENERATORS='make'
-./xwalk/gyp_xwalk xwalk/xwalk.gyp \
+export GYP_GENERATORS='ninja'
+./src/xwalk/gyp_xwalk src/xwalk/xwalk.gyp \
 --no-parallel \
 ${GYP_EXTRA_FLAGS} \
 -Dchromeos=0 \
@@ -182,55 +166,32 @@ ${GYP_EXTRA_FLAGS} \
 -Duse_gconf=0 \
 -Duse_kerberos=0 \
 -Duse_system_bzip2=1 \
--Duse_system_icu=1 \
 -Duse_system_libexif=1 \
 -Duse_system_libxml=1 \
 -Duse_system_nspr=1 \
--Denable_xi21_mt=1 \
--Duse_xi2_mt=0 \
 -Denable_hidpi=1
 
-make %{?_smp_mflags} -C "${BUILDDIR_NAME}" BUILDTYPE=Release xwalk xwalkctl xwalk_launcher xwalk-pkg-helper
+ninja %{?_smp_mflags} -C src/out/Release xwalk xwalkctl xwalk_launcher xwalk-pkg-helper
 
 %install
-# Support building in a non-standard directory, possibly outside %{_builddir}.
-# Since the build root is erased every time a new build is performed, one way
-# to avoid losing the build directory is to specify a location outside the
-# build root to the BUILDDIR_NAME definition, such as "/var/tmp/xwalk-build"
-# (remember all paths are still inside the chroot):
-#    gbs build --define 'BUILDDIR_NAME /some/path'
-BUILDDIR_NAME="%{?BUILDDIR_NAME}"
-if [ -z "${BUILDDIR_NAME}" ]; then
-   BUILDDIR_NAME="."
-fi
-
-# Since BUILDDIR_NAME can be either a relative path or an absolute one, we need
-# to cd into src/ so that it means the same thing in the build and install
-# stages: during the former, a relative location refers to a place inside src/,
-# whereas during the latter a relative location by default would refer to a
-# place one directory above src/. If BUILDDIR_NAME is an absolute path, this is
-# irrelevant anyway.
-cd src
-
 # Binaries.
-install -p -D ../xwalk %{buildroot}%{_bindir}/xwalk
+install -p -D xwalk %{buildroot}%{_bindir}/xwalk
 install -p -D %{SOURCE2} %{buildroot}%{_dbusservicedir}/org.crosswalkproject.Runtime1.service
-install -p -D ../xwalk.service %{buildroot}%{_systemduserservicedir}/xwalk.service
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalk %{buildroot}%{_libdir}/xwalk/xwalk
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalkctl %{buildroot}%{_bindir}/xwalkctl
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalk-launcher %{buildroot}%{_bindir}/xwalk-launcher
+install -p -D xwalk.service %{buildroot}%{_systemduserservicedir}/xwalk.service
+install -p -D src/out/Release/xwalk %{buildroot}%{_libdir}/xwalk/xwalk
+install -p -D src/out/Release/xwalkctl %{buildroot}%{_bindir}/xwalkctl
+install -p -D src/out/Release/xwalk-launcher %{buildroot}%{_bindir}/xwalk-launcher
 # xwalk-pkg-helper needs to be set-user-ID-root so it can finish the installation process.
-install -m 06755 -p -D ${BUILDDIR_NAME}/out/Release/xwalk-pkg-helper %{buildroot}%{_bindir}/xwalk-pkg-helper
+install -m 06755 -p -D src/out/Release/xwalk-pkg-helper %{buildroot}%{_bindir}/xwalk-pkg-helper
 
 # Supporting libraries and resources.
-install -p -D ${BUILDDIR_NAME}/out/Release/icudtl.dat %{buildroot}%{_libdir}/xwalk/icudtl.dat
-install -p -D ${BUILDDIR_NAME}/out/Release/libffmpegsumo.so %{buildroot}%{_libdir}/xwalk/libffmpegsumo.so
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalk.pak %{buildroot}%{_libdir}/xwalk/xwalk.pak
+install -p -D src/out/Release/icudtl.dat %{buildroot}%{_libdir}/xwalk/icudtl.dat
+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
 
 # Register xwalk to the package manager.
-install -p -D ../%{name}.xml %{buildroot}%{_manifestdir}/%{name}.xml
-install -p -D ../%{name}.png %{buildroot}%{_desktop_icondir}/%{name}.png
-
+install -p -D %{name}.xml %{buildroot}%{_manifestdir}/%{name}.xml
+install -p -D %{name}.png %{buildroot}%{_desktop_icondir}/%{name}.png
 
 %post
 mkdir -p %{_desktop_icondir_ro}
index 4dd44ca..16b315e 100644 (file)
@@ -240,6 +240,7 @@ _BANNED_CPP_FUNCTIONS = (
 _VALID_OS_MACROS = (
     # Please keep sorted.
     'OS_ANDROID',
+    'OS_ANDROID_HOST',
     'OS_BSD',
     'OS_CAT',       # For testing.
     'OS_CHROMEOS',
index a9cc0f4..3025730 100644 (file)
           # hence the *_android.cc files are included but the actual code
           # doesn't have OS_ANDROID / ANDROID defined.
           'conditions': [
-            # Host build on linux depends on system.gyp::gtk as
-            # default linux build has TOOLKIT_GTK defined.
-            ['host_os == "linux"', {
-              'sources/': [
-                ['include', '^atomicops_internals_x86_gcc\\.cc$'],
-              ],
-              'dependencies': [
-                '../build/linux/system.gyp:gtk',
-              ],
-              'export_dependent_settings': [
-                '../build/linux/system.gyp:gtk',
-              ],
-            }],
             ['host_os == "mac"', {
               'sources/': [
                 ['exclude', '^native_library_linux\\.cc$'],
index e130b10..3a442da 100644 (file)
             ],
           }],
           ['OS == "android" and _toolset == "host" and host_os == "linux"', {
+            'defines': [
+              'OS_ANDROID_HOST=Linux',
+            ],
             'sources/': [
               # Pull in specific files for host builds.
+              ['include', '^atomicops_internals_x86_gcc\\.cc$'],
               ['include', '^threading/platform_thread_linux\\.cc$'],
             ],
           }],
index 956f5f0..742500c 100644 (file)
@@ -38,7 +38,7 @@
 #include "base/message_loop/message_pump_x11.h"
 #elif defined(USE_OZONE) && !defined(OS_NACL)
 #include "base/message_loop/message_pump_ozone.h"
-#else
+#elif !defined(OS_ANDROID_HOST)
 #define USE_GTK_MESSAGE_PUMP
 #include "base/message_loop/message_pump_gtk.h"
 #if defined(TOOLKIT_GTK)
@@ -57,6 +57,8 @@ class RunLoop;
 class ThreadTaskRunnerHandle;
 #if defined(OS_ANDROID)
 class MessagePumpForUI;
+#elif defined(OS_ANDROID_HOST)
+typedef MessagePumpLibevent MessagePumpForUI;
 #endif
 class WaitableEvent;
 
index 65f3efd..6fbdfee 100644 (file)
@@ -1 +1 @@
-LASTCHANGE=254894
+LASTCHANGE=257853
index b5d927c..65b2400 100644 (file)
@@ -50,3 +50,8 @@ void pa_stream_unref(pa_stream* s);
 int pa_context_errno(pa_context *c);
 const char* pa_strerror(int error);
 pa_cvolume* pa_cvolume_set(pa_cvolume* a, unsigned  channels, pa_volume_t v);
+# Functions from pulse used in TIZEN to tag the audio stream as "browser".
+pa_proplist* pa_proplist_new(void);
+void pa_proplist_free(pa_proplist* p);
+int pa_proplist_sets(pa_proplist *p, const char *key, const char *value);
+pa_stream* pa_stream_new_with_proplist(pa_context* c, const char* name, const pa_sample_spec* ss, const pa_channel_map* map, pa_proplist* proplist);
index bee4790..f29ddad 100644 (file)
@@ -261,7 +261,16 @@ bool CreateOutputStream(pa_threaded_mainloop** mainloop,
     // than the default channel map (NULL).
     map = &source_channel_map;
   }
+#if defined(OS_TIZEN)
+  pa_proplist* proplist = pa_proplist_new();
+  pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "browser");
+  *stream = pa_stream_new_with_proplist(*context, "Playback",
+                                        &sample_specifications,
+                                        map, proplist);
+  pa_proplist_free(proplist);
+#else
   *stream = pa_stream_new(*context, "Playback", &sample_specifications, map);
+#endif
   RETURN_ON_FAILURE(*stream, "failed to create PA playback stream");
 
   pa_stream_set_state_callback(*stream, stream_callback, user_data);
index 140076f..0b0c7cd 100644 (file)
@@ -18,7 +18,6 @@
 namespace ozonewayland {
 
 OzoneDisplay* OzoneDisplay::instance_ = NULL;
-const int kMaxDisplaySize = 20;
 
 OzoneDisplay* OzoneDisplay::GetInstance() {
   return instance_;
@@ -28,8 +27,7 @@ OzoneDisplay::OzoneDisplay() : desktop_screen_(NULL),
     display_(NULL),
     channel_(NULL),
     host_(NULL),
-    event_converter_(NULL),
-    spec_(NULL) {
+    event_converter_(NULL) {
   instance_ = this;
 }
 
@@ -38,28 +36,6 @@ OzoneDisplay::~OzoneDisplay() {
   instance_ = NULL;
 }
 
-const char* OzoneDisplay::DefaultDisplaySpec() {
-  if (!spec_) {
-    spec_ = new char[kMaxDisplaySize];
-    if (desktop_screen_ && !desktop_screen_->geometry().size().IsEmpty())  {
-      gfx::Rect rect(desktop_screen_->geometry());
-      base::snprintf(spec_,
-                     kMaxDisplaySize,
-                     "%dx%d*2",
-                     rect.width(),
-                     rect.height());
-    } else {
-      spec_[0] = '\0';
-    }
-  }
-
-  if (spec_[0] == '\0')
-    NOTREACHED() <<
-        "OutputHandleMode should come from Wayland compositor first";
-
-  return spec_;
-}
-
 bool OzoneDisplay::InitializeHardware() {
   display_ = new WaylandDisplay(WaylandDisplay::RegisterAsNeeded);
   bool initialized_hardware = display_->display() ? true : false;
@@ -142,8 +118,6 @@ gfx::AcceleratedWidget OzoneDisplay::RealizeAcceleratedWidget(
 }
 
 void OzoneDisplay::OnOutputSizeChanged(unsigned width, unsigned height) {
-  if (spec_)
-    base::snprintf(spec_, kMaxDisplaySize, "%dx%d*2", width, height);
   if (desktop_screen_)
     desktop_screen_->SetGeometry(gfx::Rect(0, 0, width, height));
 }
@@ -165,9 +139,6 @@ void OzoneDisplay::Terminate() {
   if (!event_converter_ && !desktop_screen_)
     return;
 
-  if (spec_)
-    delete[] spec_;
-
   delete channel_;
   if (desktop_screen_) {
     delete desktop_screen_;
index eca8fb9..85855e4 100644 (file)
@@ -32,7 +32,6 @@ class OZONE_WAYLAND_EXPORT OzoneDisplay : public OutputChangeObserver {
   OzoneDisplay();
   virtual ~OzoneDisplay();
 
-  const char* DefaultDisplaySpec();
   bool InitializeHardware();
   void ShutdownHardware();
   intptr_t GetNativeDisplay();
@@ -58,7 +57,6 @@ class OZONE_WAYLAND_EXPORT OzoneDisplay : public OutputChangeObserver {
   OzoneDisplayChannel* channel_;
   OzoneDisplayChannelHost* host_;
   EventConverterOzoneWayland* event_converter_;
-  char* spec_;
   static OzoneDisplay* instance_;
   DISALLOW_COPY_AND_ASSIGN(OzoneDisplay);
 };
index f58cc83..8496160 100644 (file)
@@ -21,10 +21,6 @@ SurfaceFactoryWayland::SurfaceFactoryWayland() : initialized_(false),
 SurfaceFactoryWayland::~SurfaceFactoryWayland() {
 }
 
-const char* SurfaceFactoryWayland::DefaultDisplaySpec() {
-  return OzoneDisplay::GetInstance()->DefaultDisplaySpec();
-}
-
 gfx::Screen* SurfaceFactoryWayland::CreateDesktopScreen() {
   return OzoneDisplay::GetInstance()->CreateDesktopScreen();
 }
index aefaec6..37117f6 100644 (file)
@@ -16,7 +16,6 @@ class SurfaceFactoryWayland : public gfx::SurfaceFactoryOzone {
   SurfaceFactoryWayland();
   virtual ~SurfaceFactoryWayland();
 
-  virtual const char* DefaultDisplaySpec() OVERRIDE;
   virtual gfx::Screen* CreateDesktopScreen() OVERRIDE;
   virtual SurfaceFactoryOzone::HardwareState InitializeHardware() OVERRIDE;
   virtual intptr_t GetNativeDisplay() OVERRIDE;
index a72903d..9721f17 100644 (file)
@@ -58,8 +58,9 @@ void WindowTreeHostDelegateWayland::OnRootWindowClosed(unsigned handle) {
     aura_windows_ = NULL;
   }
 
-  if (!current_active_window_ || current_active_window_->window_ != handle ||
-        !open_windows_) {
+  if (!current_active_window_ ||
+      GetWindowHandle(current_active_window_->window_) != handle ||
+      !open_windows_) {
      return;
   }
 
@@ -67,7 +68,7 @@ void WindowTreeHostDelegateWayland::OnRootWindowClosed(unsigned handle) {
   // Set first top level window in the list of open windows as dispatcher.
   // This is just a guess of the window which would eventually be focussed.
   // We should set the correct root window as dispatcher in OnWindowFocused.
-  const std::list<gfx::AcceleratedWidget>& windows = open_windows();
+  const std::list<unsigned>& windows = open_windows();
   DesktopWindowTreeHostWayland* rootWindow =
       DesktopWindowTreeHostWayland::GetHostForAcceleratedWidget(
           windows.front());
@@ -84,7 +85,7 @@ void WindowTreeHostDelegateWayland::SetActiveWindow(
 
   // Make sure the stacking order is correct. The activated window should be
   // first one in list of open windows.
-  std::list<gfx::AcceleratedWidget>& windows = open_windows();
+  std::list<unsigned>& windows = open_windows();
   DCHECK(windows.size());
   unsigned window_handle = current_active_window_->window_;
   if (windows.front() != window_handle) {
@@ -120,7 +121,7 @@ WindowTreeHostDelegateWayland::GetCurrentCapture() const {
 const std::vector<aura::Window*>&
 WindowTreeHostDelegateWayland::GetAllOpenWindows() {
   if (!aura_windows_) {
-    const std::list<gfx::AcceleratedWidget>& windows = open_windows();
+    const std::list<unsigned>& windows = open_windows();
     DCHECK(windows.size());
     aura_windows_ = new std::vector<aura::Window*>(windows.size());
     std::transform(
@@ -147,14 +148,19 @@ void WindowTreeHostDelegateWayland::DispatchMouseEvent(
     event->StopPropagation();
 }
 
-std::list<gfx::AcceleratedWidget>&
+std::list<unsigned>&
 WindowTreeHostDelegateWayland::open_windows() {
   if (!open_windows_)
-    open_windows_ = new std::list<gfx::AcceleratedWidget>();
+    open_windows_ = new std::list<unsigned>();
 
   return *open_windows_;
 }
 
+unsigned
+WindowTreeHostDelegateWayland::GetWindowHandle(gfx::AcceleratedWidget widget) {
+  return static_cast<unsigned>(widget);
+}
+
 ui::EventProcessor* WindowTreeHostDelegateWayland::GetEventProcessor() {
   return current_dispatcher_->delegate_->GetEventProcessor();
 }
@@ -223,8 +229,8 @@ void WindowTreeHostDelegateWayland::OnWindowFocused(unsigned handle) {
   // Don't dispatch events in case a window has installed itself as capture
   // window but doesn't have the focus.
   handle_event_ = current_capture_ ? current_focus_window_ ==
-          current_capture_->GetAcceleratedWidget() : true;
-  if (current_active_window_->window_ == handle)
+          GetWindowHandle(current_capture_->GetAcceleratedWidget()) : true;
+  if (GetWindowHandle(current_active_window_->window_) == handle)
     return;
 
   // A new window should not steal focus in case the current window has a open
@@ -257,7 +263,7 @@ void WindowTreeHostDelegateWayland::OnWindowClose(unsigned handle) {
   // current_capture_ always be a valid pointer.
   if (!handle || !current_capture_)
     return;
-  if (current_capture_->window_ != handle)
+  if (GetWindowHandle(current_capture_->window_) != handle)
     return;
   DesktopWindowTreeHostWayland* window = NULL;
   window = DesktopWindowTreeHostWayland::GetHostForAcceleratedWidget(handle);
index 51dde45..cc3c2cb 100644 (file)
@@ -56,7 +56,8 @@ class WindowTreeHostDelegateWayland
 
   // Dispatches a mouse event.
   void DispatchMouseEvent(ui::MouseEvent* event);
-  std::list<gfx::AcceleratedWidget>& open_windows();
+  std::list<unsigned>& open_windows();
+  unsigned GetWindowHandle(gfx::AcceleratedWidget widget);
 
   unsigned current_focus_window_;
   bool handle_event_ :1;
@@ -70,7 +71,7 @@ class WindowTreeHostDelegateWayland
   DesktopWindowTreeHostWayland* current_capture_;
   DesktopWindowTreeHostWayland* current_active_window_;
   // List of all open windows.
-  std::list<gfx::AcceleratedWidget>* open_windows_;
+  std::list<unsigned>* open_windows_;
   // List of all open aura::Window.
   std::vector<aura::Window*>* aura_windows_;
   DISALLOW_COPY_AND_ASSIGN(WindowTreeHostDelegateWayland);
index a3f2898..03496a6 100644 (file)
         'host_forwarder_main.cc',
         'pipe_notifier.cc',
         'socket.cc',
-        # TODO(pliard): Remove this. This is needed to avoid undefined
-        # references at link time.
-        '../../../base/message_loop/message_pump_glib.cc',
-        '../../../base/message_loop/message_pump_gtk.cc',
       ],
     },
   ],
index 01de5c6..39680a0 100644 (file)
@@ -4,6 +4,7 @@
 {
   'variables': {
     'chromium_code': 1,
+    'external_ozone_views_files': [],
   },
   'target_defaults': {
     'conditions': [
           ],
         }],
         ['use_ozone==1', {
+          'sources': [
+            '<@(external_ozone_views_files)',
+          ],
           'dependencies': [
             '../ozone/ozone.gyp:ozone',
           ],
index f0e7212..af4b41b 100644 (file)
@@ -43,6 +43,9 @@
 
     'v8_use_snapshot%': 'true',
 
+    # Enable XDK profiling support by default.
+    'v8_enable_xdkprof': 1,
+
     # With post mortem support enabled, metadata is embedded into libv8 that
     # describes various parameters of the VM for use by debuggers. See
     # tools/gen-postmortem-metadata.py for details.
index 6744cb0..b31ad51 100644 (file)
@@ -1101,7 +1101,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
           EXTERNAL_##TYPE##_ELEMENTS);                                        \
       native_context()->set_##type##_array_fun(*fun);                         \
     }
-    TYPED_ARRAYS(INSTALL_TYPED_ARRAY)
+    BUILTIN_TYPED_ARRAY(INSTALL_TYPED_ARRAY)
 #undef INSTALL_TYPED_ARRAY
 
     Handle<JSFunction> data_view_fun =
index 1c332d1..9eac880 100644 (file)
@@ -43,6 +43,9 @@
 #include "string-stream.h"
 #include "vm-state-inl.h"
 
+// XDK support
+#include "third_party/xdk/xdk-v8.h"
+
 namespace v8 {
 namespace internal {
 
@@ -160,6 +163,15 @@ class CodeEventLogger::NameBuffer {
     }
   }
 
+  // XDK needs this function temporarily. It will be removed later.
+  void AppendAddress(Address address) {
+    Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
+    int size = OS::SNPrintF(buffer, "0x%x", address);
+    if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
+      utf8_pos_ += size;
+    }
+  }
+
   const char* get() { return utf8_buffer_; }
   int size() const { return utf8_pos_; }
 
@@ -656,6 +668,226 @@ class JitLogger : public CodeEventLogger {
   void* StartCodePosInfoEvent();
   void EndCodePosInfoEvent(Code* code, void* jit_handler_data);
 
+
+  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+  // XDK needs all this stuff below to generate the strings like
+  // "code-creation:..." in the same format as Logger generates.
+  // This string is sent to XDK by code_event_handler and then used for
+  // postprocessing. All these CodeCreateEvent(...) functions and helpers
+  // will be removed before commit.
+  void AppendCodeCreateHeader(NameBuffer* msg,
+                              Logger::LogEventsAndTags tag,
+                              Code* code) {
+    CHECK(msg);
+    msg->AppendBytes(kLogEventsNames[Logger::CODE_CREATION_EVENT]);
+    msg->AppendByte(',');
+    msg->AppendBytes(kLogEventsNames[tag]);
+    msg->AppendByte(',');
+    msg->AppendInt(code->kind());
+    msg->AppendByte(',');
+    msg->AppendAddress(code->instruction_start());
+    msg->AppendByte(',');
+    msg->AppendInt(code->instruction_size());
+    msg->AppendByte(',');
+  }
+
+
+  void AppendDetailed(NameBuffer* msg, String* str, bool show_impl_info) {
+    CHECK(msg);
+    if (str == NULL) return;
+    DisallowHeapAllocation no_gc;  // Ensure string stay valid.
+    int len = str->length();
+    if (len > 0x1000)
+      len = 0x1000;
+    if (show_impl_info) {
+      msg->AppendByte(str->IsOneByteRepresentation() ? 'a' : '2');
+      if (StringShape(str).IsExternal())
+        msg->AppendByte('e');
+      if (StringShape(str).IsInternalized())
+        msg->AppendByte('#');
+      msg->AppendByte(':');
+      msg->AppendInt(str->length());
+      msg->AppendByte(':');
+    }
+    for (int i = 0; i < len; i++) {
+      uc32 c = str->Get(i);
+      if (c > 0xff) {
+        msg->AppendBytes("\\u");
+        msg->AppendHex(c);
+      } else if (c < 32 || c > 126) {
+        msg->AppendBytes("\\x");
+        msg->AppendHex(c);
+      } else if (c == ',') {
+        msg->AppendBytes("\\,");
+      } else if (c == '\\') {
+        msg->AppendBytes("\\\\");
+      } else if (c == '\"') {
+        msg->AppendBytes("\"\"");
+      } else {
+        msg->AppendByte(c);
+      }
+    }
+  }
+
+
+  void AppendDoubleQuotedString(NameBuffer* msg, const char* string) {
+    CHECK(msg);
+    msg->AppendByte('"');
+    for (const char* p = string; *p != '\0'; p++) {
+      if (*p == '"') {
+        msg->AppendByte('\\');
+     }
+      msg->AppendByte(*p);
+    }
+    msg->AppendByte('"');
+  }
+
+
+  void AppendSymbolName(NameBuffer* msg, Symbol* symbol) {
+    CHECK(msg);
+    ASSERT(symbol);
+    msg->AppendBytes("symbol(");
+    if (!symbol->name()->IsUndefined()) {
+      msg->AppendByte('"');
+      AppendDetailed(msg, String::cast(symbol->name()), false);
+      msg->AppendBytes("\" ");
+    }
+    msg->AppendBytes("hash ");
+    msg->AppendHex(symbol->Hash());
+    msg->AppendByte(')');
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code, const char* comment) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, comment);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    AppendDoubleQuotedString(name_buffer_, comment);
+    LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code, Name* name) {
+    if (!xdk::XDKIsAgentAlive()) {
+       CodeEventLogger::CodeCreateEvent(tag, code, name);
+       return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    if (name->IsString()) {
+      name_buffer_->AppendByte('"');
+      AppendDetailed(name_buffer_, String::cast(name), false);
+      name_buffer_->AppendByte('"');
+    } else {
+      AppendSymbolName(name_buffer_, Symbol::cast(name));
+    }
+    LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code,
+                               SharedFunctionInfo* shared,
+                               CompilationInfo* info,
+                               Name* name) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, shared, info, name);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    if (name->IsString()) {
+      SmartArrayPointer<char> str =
+         String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+      name_buffer_->AppendByte('"');
+      name_buffer_->AppendBytes(str.get());
+      name_buffer_->AppendByte('"');
+    } else {
+      AppendSymbolName(name_buffer_, Symbol::cast(name));
+    }
+    name_buffer_->AppendByte(',');
+    name_buffer_->AppendAddress(shared->address());
+    name_buffer_->AppendByte(',');
+    name_buffer_->AppendBytes(ComputeMarker(code));
+    LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
+  }
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code,
+                               SharedFunctionInfo* shared,
+                               CompilationInfo* info,
+                               Name* source,
+                               int line, int column) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, shared,
+                                       info, source, line, column);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    SmartArrayPointer<char> name =
+        shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    name_buffer_->AppendByte('"');
+    name_buffer_->AppendBytes(name.get());
+    name_buffer_->AppendByte(' ');
+    if (source->IsString()) {
+        SmartArrayPointer<char> sourcestr =
+           String::cast(source)->ToCString(DISALLOW_NULLS,
+                                           ROBUST_STRING_TRAVERSAL);
+        name_buffer_->AppendBytes(sourcestr.get());
+    } else {
+        AppendSymbolName(name_buffer_, Symbol::cast(source));
+    }
+    name_buffer_->AppendByte(':');
+    name_buffer_->AppendInt(line);
+    name_buffer_->AppendByte(':');
+    name_buffer_->AppendInt(column);
+    name_buffer_->AppendBytes("\",");
+    name_buffer_->AppendAddress(shared->address());
+    name_buffer_->AppendByte(',');
+    name_buffer_->AppendBytes(ComputeMarker(code));
+    LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
+  }
+
+
+  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
+                               Code* code,
+                               int args_count) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::CodeCreateEvent(tag, code, args_count);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, tag, code);
+    name_buffer_->AppendBytes("\"args_count: ");
+    name_buffer_->AppendInt(args_count);
+    name_buffer_->AppendByte('"');
+  }
+
+
+  virtual void RegExpCodeCreateEvent(Code* code, String* source) {
+    if (!xdk::XDKIsAgentAlive()) {
+      CodeEventLogger::RegExpCodeCreateEvent(code, source);
+      return;
+    }
+
+    name_buffer_->Reset();
+    AppendCodeCreateHeader(name_buffer_, Logger::REG_EXP_TAG, code);
+    name_buffer_->AppendByte('"');
+    AppendDetailed(name_buffer_, source, false);
+    name_buffer_->AppendByte('"');
+  }
+
  private:
   virtual void LogRecordedBuffer(Code* code,
                                  SharedFunctionInfo* shared,
@@ -1376,8 +1608,13 @@ static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
               kLogEventsNames[Logger::CODE_CREATION_EVENT],
               kLogEventsNames[tag],
               code->kind());
-  msg->AppendAddress(code->address());
-  msg->Append(",%d,", code->ExecutableSize());
+  if (xdk::XDKIsAgentAlive()) {
+    msg->AppendAddress(code->instruction_start());
+    msg->Append(",%d,", code->instruction_size());
+  } else {
+    msg->AppendAddress(code->address());
+    msg->Append(",%d,", code->ExecutableSize());
+  }
 }
 
 
@@ -1623,11 +1860,30 @@ void Logger::MoveEventInternal(LogEventsAndTags event,
                                Address from,
                                Address to) {
   if (!FLAG_log_code || !log_->IsEnabled()) return;
+
+  Code* from_code = NULL;
+  Address to_code = NULL;
+  if (xdk::XDKIsAgentAlive()) {
+    from_code = Code::cast(HeapObject::FromAddress(from));
+    const size_t header_size =
+      from_code->instruction_start() - reinterpret_cast<byte*>(from_code);
+    to_code =
+      reinterpret_cast<byte*>(HeapObject::FromAddress(to)) + header_size;
+  }
+
   Log::MessageBuilder msg(log_);
   msg.Append("%s,", kLogEventsNames[event]);
-  msg.AppendAddress(from);
+  if (xdk::XDKIsAgentAlive()) {
+    msg.AppendAddress(from_code->instruction_start());
+  } else {
+    msg.AppendAddress(from);
+  }
   msg.Append(',');
-  msg.AppendAddress(to);
+  if (xdk::XDKIsAgentAlive()) {
+    msg.AppendAddress(to_code);
+  } else {
+    msg.AppendAddress(to);
+  }
   msg.Append('\n');
   msg.WriteToLogFile();
 }
@@ -1748,6 +2004,15 @@ void Logger::TickEvent(TickSample* sample, bool overflow) {
 }
 
 
+void Logger::XDKResumeProfiler() {
+  if (!log_->IsEnabled()) return;
+  if (profiler_ != NULL) {
+    profiler_->resume();
+    is_logging_ = true;
+  }
+}
+
+
 void Logger::StopProfiler() {
   if (!log_->IsEnabled()) return;
   if (profiler_ != NULL) {
@@ -1886,6 +2151,12 @@ void Logger::LogCodeObject(Object* object) {
 
 
 void Logger::LogCodeObjects() {
+  // Starting from Chromium v34 this function is also called from
+  // V8::Initialize. This causes reading the heap to collect already
+  // compiled methods. For XDK that must be done because XDK profiler
+  // consumes CODE_ADDED events and mantains a map of compiled methods.
+  if (xdk::XDKIsAgentAlive()) return;
+
   Heap* heap = isolate_->heap();
   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                           "Logger::LogCodeObjects");
@@ -1946,6 +2217,12 @@ void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
 
 
 void Logger::LogCompiledFunctions() {
+  // Starting from Chromium v34 this function is also called from
+  // V8::Initialize. This causes reading the heap to collect already
+  // compiled methods. For XDK that must be done because XDK profiler
+  // consumes CODE_ADDED events and mantains a map of compiled methods.
+  if (xdk::XDKIsAgentAlive()) return;
+
   Heap* heap = isolate_->heap();
   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                           "Logger::LogCompiledFunctions");
@@ -2081,10 +2358,19 @@ bool Logger::SetUp(Isolate* isolate) {
     is_logging_ = true;
   }
 
+  xdk::XDKInitializeForV8(isolate);
+
   if (FLAG_prof) {
     profiler_ = new Profiler(isolate);
     is_logging_ = true;
     profiler_->Engage();
+
+    if (xdk::XDKIsAgentAlive()) {
+      // A way to to start profiler in pause mode was removed.
+      // To pause collection of the CPU ticks we need to emulate pause.
+      // This will be removed later once XDK agent will have own sampler.
+      profiler_->pause();
+    }
   }
 
   if (FLAG_log_internal_timer_events || FLAG_prof) timer_.Start();
index d4dc76a..041ede0 100644 (file)
@@ -360,6 +360,13 @@ class Logger {
   // When data collection is paused, CPU Tick events are discarded.
   void StopProfiler();
 
+  // Resumes collection of CPU Tick events.
+  void XDKResumeProfiler();
+
+  // XDK agent uses it log code map (list of CodeAdded event
+  // before resume CPU Tick events.
+  Log* XDKGetLog() { return log_; }
+
   void LogExistingFunction(Handle<SharedFunctionInfo> shared,
                            Handle<Code> code);
   // Logs all compiled functions found in the heap.
@@ -528,15 +535,15 @@ class CodeEventLogger : public CodeEventListener {
   virtual void SharedFunctionInfoMoveEvent(Address from, Address to) { }
   virtual void CodeMovingGCEvent() { }
 
- private:
+ protected:
   class NameBuffer;
+  NameBuffer* name_buffer_;
 
+ private:
   virtual void LogRecordedBuffer(Code* code,
                                  SharedFunctionInfo* shared,
                                  const char* name,
                                  int length) = 0;
-
-  NameBuffer* name_buffer_;
 };
 
 
index a41e10a..4f65328 100644 (file)
@@ -4670,7 +4670,7 @@ class FreeSpace: public HeapObject {
 
 
 // V has parameters (Type, type, TYPE, C type, element_size)
-#define TYPED_ARRAYS(V) \
+#define BUILTIN_TYPED_ARRAY(V) \
   V(Uint8, uint8, UINT8, uint8_t, 1)                                           \
   V(Int8, int8, INT8, int8_t, 1)                                               \
   V(Uint16, uint16, UINT16, uint16_t, 2)                                       \
@@ -4679,11 +4679,18 @@ class FreeSpace: public HeapObject {
   V(Int32, int32, INT32, int32_t, 4)                                           \
   V(Float32, float32, FLOAT32, float, 4)                                       \
   V(Float64, float64, FLOAT64, double, 8)                                      \
-  V(Float32x4, float32x4, FLOAT32x4, v8::internal::float32x4_value_t, 16)      \
-  V(Int32x4, int32x4, INT32x4, v8::internal::int32x4_value_t, 16)              \
   V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1)
 
 
+#define SIMD128_TYPED_ARRAY(V) \
+  V(Float32x4, float32x4, FLOAT32x4, v8::internal::float32x4_value_t, 16)      \
+  V(Int32x4, int32x4, INT32x4, v8::internal::int32x4_value_t, 16)
+
+
+#define TYPED_ARRAYS(V) \
+  BUILTIN_TYPED_ARRAY(V) \
+  SIMD128_TYPED_ARRAY(V)
+
 
 // An ExternalArray represents a fixed-size array of primitive values
 // which live outside the JavaScript heap. Its subclasses are used to
diff --git a/src/v8/src/third_party/xdk/xdk-agent.cc b/src/v8/src/third_party/xdk/xdk-agent.cc
new file mode 100644 (file)
index 0000000..96bf8ee
--- /dev/null
@@ -0,0 +1,451 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifdef __linux__
+#include <sys/stat.h>
+#endif  // __linux__
+
+#include "xdk-agent.h"
+#include <vector>
+#include <string>
+#include <sstream>
+#include "platform.h"
+#include "log-utils.h"
+
+namespace xdk {
+namespace internal {
+
+static unsigned int XDK_COMMAND_LENGTH = 100;  // It should be enough.
+
+static const char* XDK_TRACE_FILE =
+  "/data/data/com.intel.app_analyzer/files/result.xdk2v8";
+
+static const char* XDK_MARKER_FILE =
+  "/data/data/com.intel.app_analyzer/files/profiler.run";
+
+XDKAgent XDKAgent::instance_;
+
+// SetIdle has the same semantics as CpuProfiler::SetIdle has (v8/src/api.cc)
+// It is used to tell the sampler that XDK agent is idle (it is not busy with
+// some tasks). If the agent is idle that the sampler put a IDLE VM state into
+// the Tick record. The samples happen during IDLE will be attributed to (idle)
+// line in the XDK viewer.
+static void SetIdle(bool isIdle, v8engine::Isolate* isolate) {
+  CHECK(isolate);
+  v8engine::StateTag state = isolate->current_vm_state();
+  if (isolate->js_entry_sp() != NULL) return;
+  if (state == v8engine::EXTERNAL || state == v8engine::IDLE) {
+    if (isIdle) {
+      isolate->set_current_vm_state(v8engine::IDLE);
+    } else if (state == v8engine::IDLE) {
+      isolate->set_current_vm_state(v8engine::EXTERNAL);
+    }
+  }
+}
+
+
+bool XDKAgent::setUp(v8engine::Isolate* isolate) {
+  CHECK(isolate);
+
+  if (m_isolate) {
+    // The setUp method is called for the main thread first, then may be called
+    // again if the app uses Workers (each Worker object has own V8 instance).
+    // XDK agent does not support JavaScript Worker currently.
+    XDKLog("xdk: Agent is already initialized\n");
+    return false;
+  }
+
+  FILE* file = v8engine::OS::FOpen(XDK_MARKER_FILE, "r");
+  if (file == NULL) {
+    return false;
+  }
+
+  fclose(file);
+  m_alive = true;
+  m_isolate = isolate;
+
+  return m_alive;
+}
+
+
+void XDKAgent::resumeSampling() {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  CHECK(m_isolate);
+
+  v8engine::Log* log = m_isolate->logger()->XDKGetLog();
+  CHECK(log);
+
+  // Create a new log file for new profiling session
+  CHECK(!log->IsEnabled());
+  log->Initialize(XDK_TRACE_FILE);
+
+#ifdef __linux__
+  int mode = S_IRUSR|S_IROTH|S_IRGRP|S_IWUSR|S_IWOTH|S_IWGRP;
+  if (chmod(XDK_TRACE_FILE, mode) != 0) {
+    XDKLog("xdk: Couldn't change permissions for a trace file\n");
+  }
+#endif  // __linux__
+
+  CHECK(log->IsEnabled());
+
+  logFunctionSnapshot();
+
+  // Write a marker line into the log for testing purpose
+  v8engine::Log::MessageBuilder msg(log);
+  msg.Append("Profiler started.\n");
+  msg.WriteToLogFile();
+
+  // Resume collection the CPU Tick events
+  m_isolate->logger()->XDKResumeProfiler();
+  XDKLog("xdk: Sampling is resumed\n");
+
+  SetIdle(true, m_isolate);
+}
+
+
+void XDKAgent::pauseSampling() {
+  // Pause collection the CPU Tick events
+  CHECK(m_isolate);
+  m_isolate->logger()->StopProfiler();
+
+  // Use v8 logger internals to close the trace file.
+  // Once XDK agent implements own sampler this will be removed.
+  v8engine::Log* log = m_isolate->logger()->XDKGetLog();
+  CHECK(log);
+  log->stop();
+  log->Close();
+
+  XDKLog("xdk: Sampling is stopped\n");
+}
+
+
+struct ObjectDeallocator {
+  template<typename T>
+  void operator()(const T& obj) const { delete obj.second; }
+};
+
+
+XDKAgent::~XDKAgent() {
+  CHECK(m_server != NULL);
+  CHECK(m_agent_access != NULL);
+
+  if (m_alive) {
+    CHECK(m_isolate != NULL);
+
+    m_terminate = true;
+
+    std::for_each(m_lineMaps.begin(), m_lineMaps.end(), ObjectDeallocator());
+    m_lineMaps.clear();
+
+    m_server->Shutdown();
+
+    Join();
+  }
+
+  delete m_server;
+  m_server = NULL;
+
+  delete m_agent_access;
+  m_agent_access = NULL;
+
+  m_isolate = NULL;
+}
+
+
+// The XDK listener thread.
+void XDKAgent::Run() {
+  v8engine::Isolate::EnsureDefaultIsolate();
+  v8engine::DisallowHeapAllocation no_allocation;
+  v8engine::DisallowHandleAllocation no_handles;
+  v8engine::DisallowHandleDereference no_deref;
+
+  XDKLog("xdk: Listener thread is running\n");
+  CHECK(m_server);
+
+  bool ok = m_server->Bind(m_port);
+  if (!ok) {
+    XDKLog("xdk: Unable to bind port=%d %d\n",
+            m_port, v8engine::Socket::GetLastError());
+    return;
+  }
+
+  std::vector<char> buf(XDK_COMMAND_LENGTH);
+
+  const std::string cmdStart = "start";
+  const std::string cmdStop = "stop";
+
+  while (!m_terminate) {
+    XDKLog("xdk: Listener thread is waiting for connection\n");
+
+    ok = m_server->Listen(1);
+    XDKLog("xdk: Listener thread got a connection request. Return value=%d\n",
+             v8engine::Socket::GetLastError());
+    if (ok) {
+      v8engine::Socket* client = m_server->Accept();
+      if (client == NULL) {
+        XDKLog("xdk: Accept failed %d\n", v8engine::Socket::GetLastError());
+        continue;
+      }
+
+      XDKLog("xdk: Connected\n");
+
+      int bytes_read = client->Receive(&buf[0], buf.size() - 1);
+      if (bytes_read == 0) {
+        XDKLog("xdk: Receive failed %d\n", v8engine::Socket::GetLastError());
+        break;
+      }
+      buf[bytes_read] = '\0';
+
+  #ifdef WIN32
+      if (bytes_read > 3) buf[bytes_read - 2] = '\0';  // remove CR+LF symbols
+  #else
+      if (bytes_read > 2) buf[bytes_read - 1] = '\0';  // remove LF symbol
+  #endif
+
+      std::string clientCommand(&buf[0]);
+      XDKLog("xdk: Got '%s' profiling command\n", clientCommand.c_str());
+
+      if (clientCommand == cmdStart) {
+        resumeSampling();
+      } else if (clientCommand == cmdStop) {
+        pauseSampling();
+      } else {
+        XDKLog("xdk: '%s' is not handled command\n", clientCommand.c_str());
+        break;
+      }
+    }
+  }
+
+  XDKLog("xdk: Listener thread is stopped\n");
+  return;
+}
+
+
+void XDKAgent::processCodeMovedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  v8engine::Address from = static_cast<v8engine::Address>(event->code_start);
+  v8engine::Address to = static_cast<v8engine::Address>(event->new_code_start);
+
+  if (!from || !to) return;
+  XDKLog("xdk: CODE_MOVED from=0x%x to=0x%x\n", from, to);
+  m_snapshot.move(from, to);
+}
+
+
+void XDKAgent::processCodeRemovedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  v8engine::Address addr = static_cast<v8engine::Address>(event->code_start);
+
+  if (!addr) return;
+  XDKLog("xdk: CODE_REMOVED for addr=0x%x\n", addr);
+  m_snapshot.remove(addr);
+}
+
+
+void XDKAgent::processCodeAddedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+
+  v8engine::Address codeAddr =
+    static_cast<v8engine::Address>(event->code_start);
+  uint32_t codeLen = event->code_len;
+
+  if (!codeAddr || !codeLen) return;
+  XDKLog("xdk: CODE_ADDED for addr=0x%x len=0x%x\n", codeAddr, codeLen);
+
+  // Look for line number information
+  LineMap* lineMap = NULL;
+  LineMaps::iterator itr = m_lineMaps.find(codeAddr);
+  if (itr == m_lineMaps.end()) {
+    XDKLog("xdk: Unable to find line info for addr=0x%x\n", codeAddr);
+  } else {
+    lineMap = itr->second;
+
+    // Remove line map if no chance to get source lines for it
+    v8::Handle<v8::Script> script = event->script;
+    if (*script == NULL) {
+      XDKLog("xdk: Script is empty. No line info for addr=0x%x.\n", codeAddr);
+      delete lineMap;
+      lineMap = NULL;
+      m_lineMaps.erase(codeAddr);
+    } else {
+      // Convert V8 pos value into source line number.
+      LineMap::Entries* entries =
+        const_cast<LineMap::Entries*>(lineMap->getEntries());
+      CHECK(entries);
+      CHECK(entries->size());
+      XDKLog("xdk: Found line info (%d lines) for addr=0x%x\n",
+              entries->size(), codeAddr);
+      size_t srcLine = 0;
+      LineMap::Entries::iterator lineItr = entries->begin();
+      LineMap::Entries::iterator lineEnd = entries->end();
+      for (; lineItr != lineEnd; ++lineItr) {
+        srcLine = script->GetLineNumber(lineItr->line) + 1;
+        lineItr->line = srcLine;
+        XDKLog("xdk:   offset=%p line=%d\n", lineItr->pcOffset, lineItr->line);
+      }
+    }
+  }
+
+  std::string funcType;
+  std::string name(event->name.str, event->name.len);
+  Function func(codeAddr, codeLen, name, funcType, lineMap);
+
+  if (lineMap) {
+    // Put the line number information for the given method into the trace file
+    // if profiling session is running.
+    logLineNumberInfo(codeAddr, *lineMap);
+
+    // Release memory allocated on CODE_START_LINE_INFO_RECORDING
+    delete lineMap;
+    lineMap = NULL;
+    m_lineMaps.erase(codeAddr);
+  }
+
+  m_snapshot.insert(func);
+}
+
+
+void XDKAgent::processLineMapAddedEvent(const v8::JitCodeEvent* event) {
+  v8engine::LockGuard<v8engine::Mutex> l(m_agent_access);
+  v8engine::Address codeAddr =
+    static_cast<v8engine::Address>(event->code_start);
+  void* userData = event->user_data;
+
+  if (!userData || !codeAddr) return;
+
+  LineMap* lineMap = reinterpret_cast<LineMap*>(userData);
+  if (lineMap->getSize() == 0) {
+    XDKLog("xdk: CODE_END_LINE no entries for user_data=%p addr=0x%x\n",
+            userData, codeAddr);
+    return;
+  }
+
+  std::pair<LineMaps::iterator, bool>
+    result = m_lineMaps.insert(std::make_pair(codeAddr, lineMap));
+  if (!result.second) {
+    m_lineMaps.erase(codeAddr);
+    XDKLog("xdk: removed unprocessed line info for addr=0x%x\n", codeAddr);
+    result = m_lineMaps.insert(std::make_pair(codeAddr, lineMap));
+    CHECK(result.second);
+  }
+
+  XDKLog("xdk: CODE_END_LINE added %d entries for user_data=%p addr=0x%x\n",
+           lineMap->getSize(), userData, codeAddr);
+}
+
+
+void EventHandler(const v8::JitCodeEvent* event) {
+  // This callback is called regardless of whether profiling is running.
+  //
+  // By default profiling is launched in paused mode, the agent is awaiting
+  // a command to resume profiling. At the same time, V8's JIT compiler is
+  // working. The functions which are JIT-compiled while sampling is paused
+  // are cached by V8's Logger and will be written in log (trace file) when
+  // XDK resumes the profiling. The line number info for such functions are not
+  // cached. We need to capture and cache the line number info and flush
+  // the cache on resume profiling.
+
+  if (event == NULL) return;
+
+  switch (event->type) {
+    case v8::JitCodeEvent::CODE_MOVED:
+      XDKAgent::instance().processCodeMovedEvent(event);
+      break;
+
+    case v8::JitCodeEvent::CODE_REMOVED:
+      XDKAgent::instance().processCodeRemovedEvent(event);
+      break;
+
+    case v8::JitCodeEvent::CODE_ADDED:
+      XDKAgent::instance().processCodeAddedEvent(event);
+
+    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
+      void* userData = event->user_data;
+      if (!userData) return;
+      LineMap* lineMap = reinterpret_cast<LineMap*>(userData);
+      size_t offset = event->line_info.offset;
+      size_t pos = event->line_info.pos;
+      lineMap->setPosition(offset, pos);
+      XDKLog("xdk: CODE_ADD_LINE_POS for user_data=%p offset=0x%x pos=%d\n",
+               userData, offset, pos);
+      break;
+    }
+
+    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
+      v8::JitCodeEvent* data = const_cast<v8::JitCodeEvent*>(event);
+      data->user_data = new LineMap();
+      XDKLog("xdk: CODE_START_LINE for user_data=%p\n", event->user_data);
+      break;
+    }
+
+    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
+      XDKAgent::instance().processLineMapAddedEvent(event);
+      break;
+    }
+
+    default:
+      XDKLog("xdk: Unknown event\n");
+      break;
+  }
+
+  SetIdle(true, XDKAgent::instance().isolate());
+
+  return;
+}
+
+
+void XDKAgent::logLineNumberInfo(v8engine::Address addr,
+                                 const LineMap& lineInfo) {
+  CHECK(addr);
+  v8engine::Log* log = m_isolate->logger()->XDKGetLog();
+  CHECK(log);
+  if (!log->IsEnabled()) return;
+  if (lineInfo.getSize() == 0) return;
+  const LineMap::Entries* lines = lineInfo.getEntries();
+  CHECK(lines);
+  LineMap::Entries::const_iterator lineItr = lines->begin();
+  LineMap::Entries::const_iterator lineEnd = lines->end();
+
+  // Put 'src-pos' lines into the log in our own format
+  for (; lineItr != lineEnd; ++lineItr) {
+    v8engine::Log::MessageBuilder msg(m_isolate->logger()->XDKGetLog());
+    msg.Append("src-pos,");
+    msg.Append("0x%x,%d,%d\n", addr, lineItr->pcOffset, lineItr->line);
+    msg.WriteToLogFile();
+  }
+}
+
+
+void XDKAgent::logFunctionSnapshot() {
+  CHECK(m_isolate);
+
+  CodeMap::const_iterator funcItr = m_snapshot.entries().begin();
+  CodeMap::const_iterator funcEnd = m_snapshot.entries().end();
+
+  XDKLog("FunctionSnapshot: %d entries\n", m_snapshot.entries().size());
+  if (m_snapshot.entries().size() == 0) return;
+
+  unsigned int i = 1;
+
+  for (; funcItr != funcEnd; ++funcItr, i++) {
+    const Range& range = funcItr->first;
+    const Function& func = funcItr->second;
+
+    XDKLog("%d    %s\n", i, func.getLogLine().c_str());
+
+    const LineMap& map = func.getLineMap();
+    if (map.getSize()) {
+      v8engine::Address codeAddr = range.start();
+      XDKLog("  Found %d lines for addr=%p\n", map.getSize(), codeAddr);
+      logLineNumberInfo(codeAddr, map);
+    }
+
+    // Write 'code-creation' line into the log
+    v8engine::Log::MessageBuilder msg(m_isolate->logger()->XDKGetLog());
+    msg.Append("%s\n", func.getLogLine().c_str());
+    msg.WriteToLogFile();
+  }
+}
+
+}}  // namespace xdk::internal
diff --git a/src/v8/src/third_party/xdk/xdk-agent.h b/src/v8/src/third_party/xdk/xdk-agent.h
new file mode 100644 (file)
index 0000000..183f514
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XDK_AGENT_H_
+#define XDK_AGENT_H_
+
+#include "v8.h"
+#include "sampler.h"
+#include "platform.h"
+#include "platform/socket.h"
+#include "platform/mutex.h"
+#include "xdk-types.h"
+#include "xdk-code-map.h"
+
+// ----------------------------------------------------------------------------
+//
+// This file declares XDKAgent class which does
+//
+// - Handles the code events to maintain the code map.
+// - Handles the line info events to assosiate the line info with code event.
+// - Accepts start / stop profiling commands from AppAnalyzer.
+//
+// ----------------------------------------------------------------------------
+
+namespace xdk {
+namespace internal {
+
+const int XDK_AGENT_PORT = 48899;
+
+// Callback called by V8 builtin logger.
+void EventHandler(const v8::JitCodeEvent* event);
+
+// XDK profiling agent. It starts a socket listener on the specific port and
+// handles commands to start and stop sampling.
+class XDKAgent : public v8engine::Thread {
+ public:
+  static XDKAgent& instance() {
+    return instance_;
+  }
+
+  void Run();
+
+  bool setUp(v8engine::Isolate* isolate);
+  bool isAlive() const { return m_alive; }
+
+  void processCodeMovedEvent(const v8::JitCodeEvent* event);
+  void processCodeRemovedEvent(const v8::JitCodeEvent* event);
+  void processCodeAddedEvent(const v8::JitCodeEvent* event);
+  void processLineMapAddedEvent(const v8::JitCodeEvent* event);
+
+  inline v8engine::Isolate* isolate() { return m_isolate; }
+
+ private:
+  virtual ~XDKAgent();
+  XDKAgent()
+      : v8engine::Thread("xdk:agent"),
+        m_alive(false),
+        m_port(XDK_AGENT_PORT),
+        m_server(new v8engine::Socket()),
+        m_agent_access(new v8engine::Mutex()),
+        m_isolate(NULL),
+        m_terminate(false) {
+    CHECK(m_server != NULL);
+    CHECK(m_agent_access != NULL);
+  }
+  XDKAgent(const XDKAgent&);
+  XDKAgent& operator=(const XDKAgent&);
+
+  void logFunctionSnapshot();
+  void logLineNumberInfo(v8engine::Address codeAddr, const LineMap& lineInfo);
+
+  void resumeSampling();
+  void pauseSampling();
+
+  bool m_alive;
+
+  const int m_port;  // Port to use for the agent.
+  v8engine::Socket* m_server;  // Server socket for listen/accept.
+  v8engine::Mutex* m_agent_access;
+  v8engine::Isolate* m_isolate;
+
+  // The snapshot of compiled methods at present moment.
+  FunctionSnapshot m_snapshot;
+
+  // The processLineMapAddedEvent function adds a new map for code starting
+  // address. Newly added map describes how ps offsets maps to internal pos,
+  // but not how ps offsets maps to line number within source file.
+  //
+  // On CodeAdd event, processCodeAddedEvent function looks for line map for
+  // a code address. If map is found that assign it to a object of Function type
+  // in FunctionSnapshot. Before assign the pc offset to pos map is converted
+  // to pc offset to source line.
+  //
+  // CodeMoved and CodeRemoved must not affect this map.
+  // Current understanding of V8 code generator: V8 first emits LineStart event,
+  // then bunch of LineAdd events, then LineEnd event, finally CodeAdded event.
+  // Based on above no need to add any 'smart' logic on CodeMoved and
+  // CodeRemoved for line map.
+  //
+  // Basically it should be always empty.
+  LineMaps m_lineMaps;
+
+  bool m_terminate;  // Termination flag for listening thread.
+
+  static XDKAgent instance_;
+};
+
+} }  // namespace xdk::internal
+
+#endif  // XDK_AGENT_H_
diff --git a/src/v8/src/third_party/xdk/xdk-code-map.cc b/src/v8/src/third_party/xdk/xdk-code-map.cc
new file mode 100644 (file)
index 0000000..2f25c4c
--- /dev/null
@@ -0,0 +1,145 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xdk-code-map.h"
+#include <sstream>
+
+namespace xdk {
+namespace internal {
+
+static std::string replaceAddress(const std::string& str,
+                                  v8engine::Address addr) {
+  // The input str: code-creation,LazyCompile,0,0x3851c4e0,200," native uri.js"
+  std::string first;
+  std::string end;
+
+  std::size_t found = str.find(',');
+  if (found != std::string::npos) {
+    found = str.find(',', found + 1);
+    if (found != std::string::npos) {
+      found = str.find(',', found + 1);
+      if (found != std::string::npos) {
+        first = str.substr(0, found);
+        found = str.find(',', found + 1);
+        if (found != std::string::npos) {
+          end = str.substr(found, str.size() - found);
+        }
+      }
+    }
+  }
+
+  if (!first.size() || !end.size()) return str;
+
+  std::stringstream ss;
+  ss << first << ','
+     << std::showbase << std::hex << static_cast<void*>(addr) << end;
+  return ss.str();
+}
+
+
+Function::Function(v8engine::Address codeAddr, uint32_t codeLen,
+                   const std::string& name, const std::string& type,
+                   const LineMap* lineMap)
+    : m_codeAddr(codeAddr), m_codeLen(codeLen), m_name(name), m_type(type) {
+  CHECK(codeAddr);
+  CHECK(codeLen);
+  // Can't be empty because it's came from CodeCreation(...) events
+  CHECK(!name.empty());
+  m_logLine = m_name;
+
+  if (lineMap && lineMap->getSize()) m_lineMap = *lineMap;
+}
+
+
+void FunctionSnapshot::removeAll(const Range& range) {
+  CodeMap::iterator low = m_impl.lower_bound(range);
+  CodeMap::iterator up = m_impl.upper_bound(range);
+  CodeMap::iterator::difference_type num = std::distance(low, up);
+
+  if (num) {
+    XDKLog("xdk: %d ranges were overlapped and removed\n", num);
+
+    CodeMap::iterator itr = low;
+    for (; itr != up; ++itr) {
+      XDKLog("xdk:  ovrl&removed addr=0x%x len=0x%x name=%s\n",
+             itr->first.start(), itr->first.length(),
+             itr->second.getLogLine().c_str());
+    }
+    m_impl.erase(low, up);
+  }
+}
+
+
+void FunctionSnapshot::insert(const Function& func) {
+  v8engine::Address codeAddr = func.getCodeAddress();
+  uint32_t codeLen = func.getCodeLength();
+  CHECK(codeAddr);
+  CHECK(codeLen);
+
+  Range range(codeAddr, codeLen);
+
+  removeAll(range);
+
+  std::pair<CodeMap::iterator, bool> res =
+    m_impl.insert(std::make_pair(range, func));
+  CHECK(res.second);
+
+  XDKLog("xdk: size=%d added addr=0x%x name=%s\n",
+         m_impl.size(), range.start(), func.getLogLine().c_str());
+}
+
+
+void FunctionSnapshot::remove(v8engine::Address codeAddr) {
+  if (!codeAddr) return;
+  CodeMap::iterator itr = m_impl.find(Range(codeAddr, 1));
+  if (itr != m_impl.end()) {
+    std::string name = itr->second.getLogLine();
+    uint32_t len = itr->first.length();
+    m_impl.erase(itr);
+    XDKLog("xdk: size=%d removed addr=0x%x name=%s\n",
+           m_impl.size(), codeAddr, len, name.c_str());
+  }
+}
+
+
+void FunctionSnapshot::move(v8engine::Address from, v8engine::Address to) {
+  if (!from || !to) return;
+  if (from == to) return;
+
+  CodeMap::iterator itr = m_impl.find(Range(from, 1));
+  if (itr == m_impl.end()) {
+    XDKLog("xdk: couldn't find a code to move from=0x%x to=0x%x\n", from, to);
+    return;
+  }
+  if (itr->first.start() != from) {
+    XDKLog("xdk: discarded move from=0x%x to=0x%x\n", from, to);
+    return;
+  }
+
+  uint32_t codeLen = itr->second.getCodeLength();
+  const LineMap& lines = itr->second.getLineMap();
+
+  // In case of CodeMoved we have to check that name contains the same code
+  // addr and code length as the input params and replace if they are different.
+  const std::string& orig = itr->second.getName();
+  std::string name = replaceAddress(orig, to);
+
+  const std::string& type = itr->second.getType();
+  Function toEntry(to, codeLen, name, type, &lines);
+
+  m_impl.erase(itr);
+
+  Range range(to, codeLen);
+  removeAll(range);
+
+  // Now ready to move
+
+  bool ok = m_impl.insert(std::make_pair(range, toEntry)).second;
+  CHECK(ok);
+
+  XDKLog("xdk: size=%d moved from=0x%x to=0x%x name=%s\n",
+         m_impl.size(), from, to, toEntry.getLogLine().c_str());
+}
+
+} }  // namespace xdk::internal
diff --git a/src/v8/src/third_party/xdk/xdk-code-map.h b/src/v8/src/third_party/xdk/xdk-code-map.h
new file mode 100644 (file)
index 0000000..18e3c09
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XDK_CODE_MAP_H_
+#define XDK_CODE_MAP_H_
+
+// ----------------------------------------------------------------------------
+//
+// This file contains the FunctionSnapshot and related objects declarations
+//
+// The FunctionSnapshot object maintains a map of JIT compiled functions.
+// It is modified on code events(CodeAdded, CodeMoved and CodeDeleted) from
+// V8 built-in profiler.
+//
+// ----------------------------------------------------------------------------
+
+#include "xdk-types.h"
+#include <map>
+#include <list>
+#include <string>
+#include <algorithm>
+
+namespace xdk {
+namespace internal {
+
+class LineMap;
+typedef std::map<
+          v8engine::Address,  // start address of code
+          LineMap*> LineMaps;
+
+// This class is used to record the JITted code position info for JIT
+// code profiling.
+class LineMap {
+ public:
+  struct LineEntry {
+    LineEntry(size_t offset, size_t line)
+      : pcOffset(offset), line(line) { }
+
+    size_t pcOffset;  // PC offset from the begining of the code trace.
+    size_t line;      // Can be either position returned from V8 assembler
+                      // (which needs to be converted to src line) or src line
+                      // number.
+  };
+
+  typedef std::list<LineEntry> Entries;
+
+  void setPosition(size_t offset, size_t line) {
+    addCodeLineEntry(LineEntry(offset, line));
+  }
+
+  inline size_t getSize() const { return m_lines.size(); }
+  const Entries* getEntries() const { return &m_lines; }
+
+ private:
+  void addCodeLineEntry(const LineEntry& entry) { m_lines.push_back(entry); }
+
+  Entries m_lines;
+};
+
+// This class describes the function reported with CodeAdded event.
+class Function {
+ public:
+  explicit Function(v8engine::Address codeAddr, uint32_t codeLen,
+                    const std::string& name, const std::string& type,
+                    const LineMap* lineMap);
+
+  inline v8engine::Address getCodeAddress() const { return m_codeAddr; }
+  inline uint32_t getCodeLength() const { return m_codeLen; }
+
+  inline const std::string& getType() const { return m_type; }
+  inline const std::string& getName() const { return m_name; }
+  inline const std::string& getLogLine() const { return m_logLine; }
+
+  const LineMap& getLineMap() const { return m_lineMap; }
+
+ private:
+  v8engine::Address m_codeAddr;
+  uint32_t m_codeLen;
+  std::string m_name;
+  std::string m_type;
+  std::string m_logLine;
+  LineMap m_lineMap;
+};
+
+// This class describes the code range related to object of Function type.
+// The start address and length are taken from CodeAdded event.
+class Range {
+ public:
+  class Comparator : public std::binary_function<Range&, Range&, bool> {
+   public:
+     bool operator()(const Range& l, const Range& r) const {
+       return (l.start() + l.length() <= r.start());
+     }
+  };
+
+  Range(v8engine::Address start, uint32_t length)
+    : m_start(start), m_length(length) { }
+
+  inline v8engine::Address start() const { return m_start; }
+  inline uint32_t length() const { return m_length; }
+
+ private:
+  v8engine::Address m_start;
+  uint32_t m_length;
+};
+
+// This class maintains a map of JIT compiled functions.
+// The content is changed on CodeAdded, CodeMoved and CodeDeleted events.
+typedef std::map<Range, const Function, Range::Comparator> CodeMap;
+
+class FunctionSnapshot {
+ public:
+  explicit FunctionSnapshot() {}
+  virtual ~FunctionSnapshot() { m_impl.clear(); }
+
+  void insert(const Function& func);
+  void move(v8engine::Address from, v8engine::Address to);
+  void remove(v8engine::Address addr);
+
+  inline const CodeMap& entries() { return m_impl; }
+
+ private:
+  FunctionSnapshot(const FunctionSnapshot&);
+  FunctionSnapshot& operator=(const FunctionSnapshot&);
+
+  void removeAll(const Range& range);
+
+  CodeMap m_impl;
+};
+
+} }  // namespace xdk::internal
+
+#endif  // XDK_CODE_MAP_H_
diff --git a/src/v8/src/third_party/xdk/xdk-types.h b/src/v8/src/third_party/xdk/xdk-types.h
new file mode 100644 (file)
index 0000000..4fc9fd0
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XDK_TYPES_H_
+#define XDK_TYPES_H_
+
+#include "v8.h"
+#include "platform.h"
+
+namespace v8engine = v8::internal;
+
+static void XDKLog(const char* msg, ...) {
+#if DEBUG
+  va_list arguments;
+  va_start(arguments, msg);
+  v8engine::OS::VPrint(msg, arguments);
+  va_end(arguments);
+#endif
+}
+
+#endif  // XDK_TYPES__H_
+
diff --git a/src/v8/src/third_party/xdk/xdk-v8.cc b/src/v8/src/third_party/xdk/xdk-v8.cc
new file mode 100644 (file)
index 0000000..a2ac333
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "../../../include/v8.h"
+#include "xdk-v8.h"
+#include "xdk-agent.h"
+
+namespace xdk {
+
+void XDKInitializeForV8(v8::internal::Isolate* isolate) {
+  if (!internal::XDKAgent::instance().setUp(isolate)) return;
+
+  XDKLog("xdk: XDKInitializeForV8\n");
+
+  // The --prof flag is requred for now to enable the CPU ticks collection.
+  // This flag will be removed once xdk agent implements own sampler.
+  const char* flags = "--prof";
+  v8::V8::SetFlagsFromString(flags, static_cast<int>(strlen(flags)));
+
+  v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault,
+                                 xdk::internal::EventHandler);
+
+  internal::XDKAgent::instance().Start();
+}
+
+
+bool XDKIsAgentAlive() {
+  return internal::XDKAgent::instance().isAlive();
+}
+
+}  // namespace xdk
diff --git a/src/v8/src/third_party/xdk/xdk-v8.gyp b/src/v8/src/third_party/xdk/xdk-v8.gyp
new file mode 100644 (file)
index 0000000..10f3b3b
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (c) 2013 Intel Corporation. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'v8_code': 1,
+   },
+  'includes': ['../../../build/toolchain.gypi', '../../../build/features.gypi'],
+  'targets': [
+    {
+      'target_name': 'v8_xdk',
+      'type': 'static_library',
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ],
+      'include_dirs+': [
+        '../../',
+      ],
+      'sources': [
+        'xdk-v8.h',
+        'xdk-v8.cc',
+        'xdk-agent.h',
+        'xdk-agent.cc',
+        'xdk-code-map.h',
+        'xdk-code-map.cc',
+        'xdk-types.h',
+      ],
+      'direct_dependent_settings': {
+        'conditions': [
+          ['OS != "win"', {
+            'libraries': ['-ldl',],
+          }],
+        ],
+      },
+    },
+  ]
+}
diff --git a/src/v8/src/third_party/xdk/xdk-v8.h b/src/v8/src/third_party/xdk/xdk-v8.h
new file mode 100644 (file)
index 0000000..56e717f
--- /dev/null
@@ -0,0 +1,107 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_XDK_H_
+#define V8_XDK_H_
+
+// ----------------------------------------------------------------------------
+//
+//                          XDK profiling support for V8
+//
+//  SOURCES:
+//
+//  1. XDK agent source files are located in v8/src/third_party/xdk folder.
+//
+//       To integrate this stuff into V8 build system you need to modify
+//       two v8 files:
+//
+//       1. v8/build/features.gypi
+//           'v8_enable_xdkprof': 1,
+//       2. v8/tools/gyp/v8.gyp
+//           ['v8_enable_xdkprof==1', {
+//             'dependencies': ['../../src/third_party/xdk/xdk-v8.gyp:v8_xdk',],
+//           }],
+//
+//  2. Two V8 files v8/src/log.cc and v8/src/log.h need to be modified
+//
+//       The changes related to start CPU ticks collection using V8 built-in
+//       profiler.
+//       We are working on reduce these changes up to 2 lines:
+//
+//           #include "third_party/xdk/xdk-v8.h"
+//           bool Logger::SetUp(Isolate* isolate) {
+//             ...
+//             xdk::XDKInitializeForV8(isolate);
+//             ...
+//           }
+//
+//  OVERVIEW:
+//
+//  Start up
+//
+//    XDK agent is initialized as a part of V8 built-in profiler on process
+//    start up. V8 built-in profiler should be paused (CPU ticks are not
+//    collected).
+//
+//           v8/src/log.cc:
+//           bool Logger::SetUp(Isolate* isolate) {
+//             ...
+//             xdk::XDKInitializeForV8(isolate);
+//             ...
+//           }
+//
+//      XDKInitializeForV8() function
+//      1. Checks whether XDK agent can be initialized. If a marker file is not
+//         found that initialization will be discarded.
+//      2. Starts a listener thread to accept start / stop profiling command
+//         from AppAnalyzer (xdk/xdk-agent.cc).
+//      3. Registeres a callback to consume the CodeAdded, CodeMoved,
+//         CodeDeleted events and events related to source line info by
+//         the agent.
+//
+//  Runtime
+//
+//    XDK profiler consumes the code events (EventHandler() in xdk/xdk-agent.cc)
+//    V8 emits these events even when CPU ticks collection is paused.
+//    The profiler uses the code events to maintain a function snapshot (list of
+//    code ranges assosiated with function name and source line info)
+//    (xdk-code-map.cc).
+//
+//    Start profiling
+//
+//      When the profiler receives a command to start profiling that it calls
+//      resumeSampling() (xdk/xdk-agent.cc) which
+//      1. Creates a new trace file to log the ticks and code events
+//      2. Puts the function snapshot into the trace file
+//      3. Resumes CPU ticks collection
+//
+//    Stop profiling
+//
+//      When the profiler receives a command to stop profiling that it calls
+//      pauseSampling() (xdk/xdk-agent.cc) which stops the CPU ticks collection.
+//      Note that the agent continues to consume the code events to maintain
+//      the function snapshot.
+//
+//      When collection is stopped that AppAnalyzer takes the trace file for
+//      processing.
+//
+// ----------------------------------------------------------------------------
+
+namespace xdk {
+
+// This function
+// - Overrides the V8 flags to specify a new logfile for writting profiling data
+//   (CPU ticks and Code* events).
+// - Registers callback to get line number info and code events from V8 built-in
+//   profiler. These data are needed to mantain the code map.
+// - Starts the XDK agent listener thread which is awaiting for start and stop
+//   profiling commands.
+void XDKInitializeForV8(v8::internal::Isolate* isolate);
+
+bool XDKIsAgentAlive();
+
+}  // namespace XDK
+
+#endif  // V8_XDK_H_
+
index 11ba080..ccebcec 100755 (executable)
 #  - _GLOBAL__I__ZN2v810LineEditor6first_E
 #  - _GLOBAL__I__ZN2v88internal32AtomicOps_Internalx86CPUFeaturesE
 #  - _GLOBAL__I__ZN2v88internal8ThreadId18highest_thread_id_E
-expected_static_init_count=3
+
+# The XDK CPU profiler patch adds one more static initializer.
+# - _GLOBAL__sub_I__ZN3xdk8internal8XDKAgent9instance_E
+expected_static_init_count=4
 
 v8_root=$(readlink -f $(dirname $BASH_SOURCE)/../)
 
index e4a0416..43d70e1 100644 (file)
         }, {
           'toolsets': ['target'],
         }],
+       ['v8_enable_xdkprof==1', {
+          'dependencies': ['../../src/third_party/xdk/xdk-v8.gyp:v8_xdk',],
+        }],
         ['v8_target_arch=="arm"', {
           'sources': [  ### gcmole(arch:arm) ###
             '../../src/arm/assembler-arm-inl.h',
index d3137ee..c80c1c5 100644 (file)
@@ -7,9 +7,9 @@
 # Use 'Trunk' for trunk.
 # If using trunk, will use '.DEPS.git' for gclient.
 chromium_version = '34.0.1847.45'
-chromium_crosswalk_point = 'cb7bc58aa1239e2fa92d692e81ccd06fa6c82722'
+chromium_crosswalk_point = 'b83e11e691378bba3b997c6c7667908c4cd33798'
 blink_crosswalk_point = 'e8b6b995b38b422c2b4d58fa5201599f1e510537'
-v8_crosswalk_point = '702dcf9c6e58d90e85594fbe54579ade631fe3b5'
+v8_crosswalk_point = 'ffe72f9229923611866423ced472b1dff97abdfe'
 
 deps_xwalk = {
   'src': 'https://github.com/crosswalk-project/chromium-crosswalk.git@%s' % chromium_crosswalk_point,
@@ -17,7 +17,7 @@ deps_xwalk = {
   'src/v8': 'https://github.com/crosswalk-project/v8-crosswalk.git@%s' % v8_crosswalk_point,
 
   # Ozone-Wayland is required for Wayland support in Chromium.
-  'src/ozone': 'https://github.com/01org/ozone-wayland.git@39d93a66777395d5c9ca11da95c436b9192d9725',
+  'src/ozone': 'https://github.com/01org/ozone-wayland.git@a4e3e96b1e1c51cecf5f7bc162b0d98064c95bc2',
 }
 vars_xwalk = {
 }
index 456d7c8..d2d743c 100644 (file)
@@ -1,4 +1,4 @@
-MAJOR=5
+MAJOR=6
 MINOR=34
-BUILD=105
+BUILD=113
 PATCH=0
index be0c240..f0c556b 100644 (file)
@@ -5,7 +5,10 @@
 package org.xwalk.app.template;
 
 import android.graphics.Color;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
+import android.view.WindowManager;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.TextView;
@@ -42,4 +45,26 @@ public class AppTemplateActivity extends XWalkRuntimeActivityBase {
             setContentView(msgText);
         }
     }
+
+    private void enterFullscreen() {
+        if (VERSION.SDK_INT >= VERSION_CODES.KITKAT &&
+                ((getWindow().getAttributes().flags &
+                        WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0)) {
+            View decorView = getWindow().getDecorView();
+            decorView.setSystemUiVisibility(
+                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+                    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+                    View.SYSTEM_UI_FLAG_FULLSCREEN |
+                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+        }
+    }
+
+    public void setIsFullscreen(boolean isFullscreen) {
+        if (isFullscreen) {
+            enterFullscreen();
+        }
+    }
+
 }
index c8eac2e..675b67b 100755 (executable)
@@ -114,8 +114,8 @@ def CustomizeThemeXML(sanitized_name, fullscreen, launch_screen_img):
 
 
 def CustomizeXML(sanitized_name, package, app_versionCode, app_version,
-                 description, name, orientation, icon, fullscreen,
-                 launch_screen_img, permissions):
+                 description, name, orientation, icon_dict, fullscreen,
+                 launch_screen_img, permissions, app_root):
   manifest_path = os.path.join(sanitized_name, 'AndroidManifest.xml')
   if not os.path.isfile(manifest_path):
     print ('Please make sure AndroidManifest.xml'
@@ -143,19 +143,9 @@ def CustomizeXML(sanitized_name, package, app_versionCode, app_version,
   if orientation:
     EditElementAttribute(xmldoc, 'activity', 'android:screenOrientation',
                          orientation)
-  if icon and os.path.isfile(icon):
-    drawable_path = os.path.join(sanitized_name, 'res', 'drawable')
-    if not os.path.exists(drawable_path):
-      os.makedirs(drawable_path)
-    icon_file = os.path.basename(icon)
-    icon_file = ReplaceInvalidChars(icon_file)
-    shutil.copyfile(icon, os.path.join(drawable_path, icon_file))
-    icon_name = os.path.splitext(icon_file)[0]
-    EditElementAttribute(xmldoc, 'application',
-                         'android:icon', '@drawable/%s' % icon_name)
-  elif icon and (not os.path.isfile(icon)):
-    print ('Please make sure the icon file does exist!')
-    sys.exit(6)
+  if CustomizeIcon(sanitized_name, app_root, icon_dict):
+    EditElementAttribute(xmldoc, 'application', 'android:icon',
+                         '@drawable/icon')
 
   file_handle = open(os.path.join(sanitized_name, 'AndroidManifest.xml'), 'w')
   xmldoc.writexml(file_handle, encoding='utf-8')
@@ -172,21 +162,21 @@ def ReplaceString(file_path, src, dest):
   file_handle.close()
 
 
-def SetVariable(file_path, variable, value):
+def SetVariable(file_path, string_line, variable, value):
   function_string = ('%sset%s(%s);\n' %
                     ('        ', variable, value))
   temp_file_path = file_path + '.backup'
   file_handle = open(temp_file_path, 'w+')
   for line in open(file_path):
     file_handle.write(line)
-    if (line.find('public void onCreate(Bundle savedInstanceState)') >= 0):
+    if (line.find(string_line) >= 0):
       file_handle.write(function_string)
   file_handle.close()
   shutil.move(temp_file_path, file_path)
 
 
 def CustomizeJava(sanitized_name, package, app_url, app_local_path,
-                  enable_remote_debugging):
+                  enable_remote_debugging, display_as_fullscreen):
   root_path =  os.path.join(sanitized_name, 'src',
                             package.replace('.', os.path.sep))
   dest_activity = os.path.join(root_path, sanitized_name + 'Activity.java')
@@ -214,7 +204,13 @@ def CustomizeJava(sanitized_name, package, app_url, app_local_path,
         sys.exit(8)
 
   if enable_remote_debugging:
-    SetVariable(dest_activity, 'RemoteDebugging', 'true')
+    SetVariable(dest_activity,
+                'public void onCreate(Bundle savedInstanceState)',
+                'RemoteDebugging', 'true')
+  if display_as_fullscreen:
+    SetVariable(dest_activity,
+                'super.onCreate(savedInstanceState)',
+                'IsFullscreen', 'true')
 
 
 def CopyExtensionFile(extension_name, suffix, src_path, dest_path):
@@ -337,19 +333,53 @@ def CustomizeExtensions(sanitized_name, name, extensions):
     extension_json_file.close()
 
 
+def CustomizeIcon(sanitized_name, app_root, icon_dict):
+  icon_exist = False
+  drawable_dict = {'ldpi':[1, 37], 'mdpi':[37, 72], 'hdpi':[72, 96],
+                   'xhdpi':[96, 120], 'xxhdpi':[120, 144]}
+  if not icon_dict:
+    return icon_exist
+
+  try:
+    icon_dict = dict((int(k), v) for k, v in icon_dict.items())
+  except ValueError:
+    print('The key of icon in the manifest file should be a number.')
+
+  if len(icon_dict) > 0:
+    icon_list = sorted(icon_dict.iteritems(), key = lambda d:d[0])
+    for kd, vd in drawable_dict.iteritems():
+      for item in icon_list:
+        if item[0] >= vd[0] and item[0] < vd[1]:
+          drawable_path = os.path.join(sanitized_name, 'res', 'drawable-' + kd)
+          if not os.path.exists(drawable_path):
+            os.makedirs(drawable_path)
+          icon = os.path.join(app_root, item[1])
+          if icon and os.path.isfile(icon):
+            icon_name = os.path.basename(icon)
+            icon_suffix = icon_name.split('.')[-1]
+            shutil.copyfile(icon, os.path.join(drawable_path,
+                                               'icon.' + icon_suffix))
+            icon_exist = True
+          elif icon and (not os.path.isfile(icon)):
+            print ('Error: Please make sure \"' + icon + '\" does exist!')
+            sys.exit(6)
+          break
+  return icon_exist
+
+
 def CustomizeAll(app_versionCode, description, icon, permissions, app_url,
                  app_root, app_local_path, enable_remote_debugging,
-                 fullscreen_flag, extensions, launch_screen_img,
+                 display_as_fullscreen, extensions, launch_screen_img,
                  package='org.xwalk.app.template', name='AppTemplate',
-                 app_version='1.0.0', orientation='unspecified'):
+                 app_version='1.0.0', orientation='unspecified') :
   sanitized_name = ReplaceInvalidChars(name, 'apkname')
   try:
     Prepare(sanitized_name, package, app_root)
     CustomizeXML(sanitized_name, package, app_versionCode, app_version,
-                 description, name, orientation, icon, fullscreen_flag,
-                 launch_screen_img, permissions)
+                 description, name, orientation, icon, display_as_fullscreen,
+                 launch_screen_img, permissions, app_root)
     CustomizeJava(sanitized_name, package, app_url, app_local_path,
-                  enable_remote_debugging)
+                  enable_remote_debugging, display_as_fullscreen)
     CustomizeExtensions(sanitized_name, name, extensions)
   except SystemExit as ec:
     print('Exiting with error code: %d' % ec.code)
@@ -370,8 +400,6 @@ def main():
   info = ('The application description. Such as:'
           '--description=YourApplicationdDescription')
   parser.add_option('--description', help=info)
-  info = ('The path of icon. Such as: --icon=/path/to/your/customized/icon')
-  parser.add_option('--icon', help=info)
   info = ('The permission list. Such as: --permissions="geolocation"'
           'For more permissions, such as:'
           '--permissions="geolocation:permission2"')
@@ -408,7 +436,21 @@ def main():
                     help='The fallback image for launch_screen')
   options, _ = parser.parse_args()
   try:
-    CustomizeAll(options.app_versionCode, options.description, options.icon,
+    icon_dict = {144: 'icons/icon_144.png',
+                 72: 'icons/icon_72.png',
+                 96: 'icons/icon_96.png',
+                 48: 'icons/icon_48.png'}
+    if options.name == None:
+      options.name = 'Example'
+    if options.app_root == None:
+      options.app_root = os.path.join('test_data', 'manifest')
+    if options.package == None:
+      options.package = 'org.xwalk.app.template'
+    if options.orientation == None:
+      options.orientation = 'unspecified'
+    if options.app_version == None:
+      options.app_version = '1.0.0'
+    CustomizeAll(options.app_versionCode, options.description, icon_dict,
                  options.permissions, options.app_url, options.app_root,
                  options.app_local_path, options.enable_remote_debugging,
                  options.fullscreen, options.extensions,
index f096cdb..8c4901f 100755 (executable)
@@ -111,15 +111,7 @@ def ParseManifest(options):
     sys.exit(9)
   if parser.GetAppRoot():
     options.app_root = parser.GetAppRoot()
-    temp_dict = parser.GetIcons()
-    try:
-      icon_dict = dict((int(k), v) for k, v in temp_dict.items())
-    except ValueError:
-      print('The key of icon in the manifest file should be a number.')
-    # TODO(junmin): add multiple icons support.
-    if icon_dict:
-      icon_file = max(iter(icon_dict.items()), key=operator.itemgetter(0))[1]
-      options.icon = os.path.join(options.app_root, icon_file)
+    options.icon_dict = parser.GetIcons()
   if parser.GetFullScreenFlag().lower() == 'true':
     options.fullscreen = True
   elif parser.GetFullScreenFlag().lower() == 'false':
@@ -195,13 +187,10 @@ def Customize(options):
   name = 'AppTemplate'
   if options.name:
     name = options.name
-  app_version = '1.0.0'
+  app_version = ''
   if options.app_version:
     app_version = options.app_version
   app_versionCode = MakeVersionCode(options)
-  icon = ''
-  if options.icon:
-    icon = os.path.expanduser(options.icon)
   app_root = ''
   if options.app_root:
     app_root = os.path.expanduser(options.app_root)
@@ -214,7 +203,7 @@ def Customize(options):
   orientation = 'unspecified'
   if options.orientation:
     orientation = options.orientation
-  CustomizeAll(app_versionCode, options.description, icon,
+  CustomizeAll(app_versionCode, options.description, options.icon_dict,
                options.permissions, options.app_url, app_root,
                options.app_local_path, remote_debugging,
                fullscreen_flag, options.extensions,
@@ -702,18 +691,24 @@ def main(argv):
     if options.permissions:
       permission_list = options.permissions.split(':')
     else:
-      print ('Warning: all supported permissions on Android port are added. '
-             'Refer to https://github.com/crosswalk-project/'
-             'crosswalk-website/wiki/Crosswalk-manifest')
+      print('Warning: all supported permissions on Android port are added. '
+            'Refer to https://github.com/crosswalk-project/'
+            'crosswalk-website/wiki/Crosswalk-manifest')
       permission_list = permission_mapping_table.keys()
     options.permissions = HandlePermissionList(permission_list)
-
+    options.icon_dict = {}
   else:
     try:
       ParseManifest(options)
     except SystemExit as ec:
       return ec.code
 
+  if (options.app_root and options.app_local_path and not
+      os.path.isfile(os.path.join(options.app_root, options.app_local_path))):
+    print('Please make sure that the local path file of launching app '
+          'does exist.')
+    sys.exit(7)
+
   options.name = ReplaceInvalidChars(options.name, 'apkname')
   options.package = ReplaceInvalidChars(options.package)
   sanitized_name = ReplaceInvalidChars(options.name, 'apkname')
index ffed605..e49e15a 100755 (executable)
@@ -270,6 +270,19 @@ class TestMakeApk(unittest.TestCase):
     self.checkApks('Example', '1.0.0')
     Clean('Example', '1.0.0')
 
+  def testPermissionsWithError(self):
+    cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
+           '--package=org.xwalk.example', '--permissions=UndefinedPermission',
+           '--app-url=http://www.intel.com', self._mode]
+    out = RunCommand(cmd)
+    self.assertTrue(out.find('related API is not supported.') != -1)
+    cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
+           '--package=org.xwalk.example',
+           '--permissions=Contacts.Geolocation.Messaging',
+           '--app-url=http://www.intel.com', self._mode]
+    out = RunCommand(cmd)
+    self.assertTrue(out.find('related API is not supported.') != -1)
+
   def testPackage(self):
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            self._mode]
@@ -331,17 +344,24 @@ class TestMakeApk(unittest.TestCase):
     self.assertFalse(os.path.exists('Example.apk'))
     Clean('Example', '1.0.0')
 
+    manifest_path = os.path.join('test_data', 'manifest',
+                                 'manifest_app_launch_local_path.json')
+    cmd = ['python', 'make_apk.py', '--manifest=%s' % manifest_path, self._mode]
+    out = RunCommand(cmd)
+    self.assertTrue(out.find('Please make sure that the local path file') != -1)
+    self.assertFalse(os.path.exists('Example.apk'))
+    Clean('Example', '1.0.0')
+
   def testIcon(self):
-    icon_path = './app_src/res/drawable-xhdpi/crosswalk.png'
+    manifest_path = os.path.join('test_data', 'manifest', 'manifest_icon.json')
     cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
            '--package=org.xwalk.example', '--app-url=http://www.intel.com',
-           '--icon=%s' % icon_path, self._mode]
+           '--manifest=%s' % manifest_path, self._mode]
     RunCommand(cmd)
     manifest = 'Example/AndroidManifest.xml'
     with open(manifest, 'r') as content_file:
       content = content_file.read()
-    self.assertTrue(content.find('crosswalk') != -1)
-    self.assertTrue(os.path.exists('Example/res/drawable'))
+    self.assertTrue(content.find('drawable/icon') != -1)
     self.checkApks('Example', '1.0.0')
     Clean('Example', '1.0.0')
 
@@ -602,8 +622,10 @@ class TestMakeApk(unittest.TestCase):
     icon_path = './app_src/res/drawable-xhdpi/crosswalk.png'
     extension_path = 'test_data/extensions/myextension'
     arch = ''
+    icon = ''
     if exec_file.find("make_apk.py") != -1:
       arch = '--arch=x86'
+      icon = '--icon=%s' % icon_path
     cmd = ['python', '%s' % exec_file,
            '--app-version=1.0.0',
            '--app-url=http://www.intel.com',
@@ -612,7 +634,7 @@ class TestMakeApk(unittest.TestCase):
            '--enable-remote-debugging',
            '--extensions=%s' % extension_path,
            '--fullscreen',
-           '--icon=%s' % icon_path,
+           '%s' % icon,
            '--name=Example',
            '--orientation=landscape',
            '--package=org.xwalk.example',
@@ -637,8 +659,6 @@ class TestMakeApk(unittest.TestCase):
     self.assertTrue(content.find('versionName') != -1)
     # Test orientation option.
     self.assertTrue(content.find('landscape') != -1)
-    # Test icon option.
-    self.assertTrue(os.path.exists('Example/res/drawable'))
     # Test fullscreen option
     theme = 'Example/res/values/theme.xml'
     with open(theme, 'r') as content_file:
@@ -730,6 +750,7 @@ def SuiteWithModeOption():
   test_suite.addTest(TestMakeApk('testOrientation'))
   test_suite.addTest(TestMakeApk('testPackage'))
   test_suite.addTest(TestMakeApk('testPermissions'))
+  test_suite.addTest(TestMakeApk('testPermissionsWithError'))
   test_suite.addTest(TestMakeApk('testXPK'))
   test_suite.addTest(TestMakeApk('testXPKWithError'))
   test_suite.addTest(TestMakeApk('testTargetDir'))
index 3a1f281..9f61231 100755 (executable)
@@ -134,10 +134,10 @@ class ManifestJsonParser(object):
     ret_dict['plugin'] = ''
     if 'plugin' in self.data_src:
       ret_dict['plugin'] = self.data_src['plugin']
-    if 'fullscreen' in self.data_src:
-      ret_dict['fullscreen'] = self.data_src['fullscreen']
+    if 'display' in self.data_src and 'fullscreen' in self.data_src['display']:
+      ret_dict['fullscreen'] = 'true'
     else:
-      ret_dict['fullscreen'] = 'False'
+      ret_dict['fullscreen'] = ''
     ret_dict['launch_screen_img'] = ''
     if 'launch_screen' in self.data_src:
       if 'default' not in self.data_src['launch_screen']:
diff --git a/src/xwalk/app/tools/android/test_data/manifest/icons/icon_144.png b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_144.png
new file mode 100644 (file)
index 0000000..b69b4e8
Binary files /dev/null and b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_144.png differ
diff --git a/src/xwalk/app/tools/android/test_data/manifest/icons/icon_48.png b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_48.png
new file mode 100644 (file)
index 0000000..e87864a
Binary files /dev/null and b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_48.png differ
diff --git a/src/xwalk/app/tools/android/test_data/manifest/icons/icon_72.png b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_72.png
new file mode 100644 (file)
index 0000000..fc19a3e
Binary files /dev/null and b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_72.png differ
diff --git a/src/xwalk/app/tools/android/test_data/manifest/icons/icon_96.png b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_96.png
new file mode 100644 (file)
index 0000000..5989755
Binary files /dev/null and b/src/xwalk/app/tools/android/test_data/manifest/icons/icon_96.png differ
index db02b81..fb355be 100644 (file)
@@ -18,5 +18,5 @@
     "Messaging"],
   "required_version": "1.28.1.0",
   "plugin": [],
-  "fullscreen":"true"
+  "display": ["fullscreen"]
 }
diff --git a/src/xwalk/app/tools/android/test_data/manifest/manifest_icon.json b/src/xwalk/app/tools/android/test_data/manifest/manifest_icon.json
new file mode 100644 (file)
index 0000000..44a8274
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  "name": "Example",
+  "version": "1.0.0",
+  "launch_path": "http://www.intel.com",
+  "app": {
+      "launch": {
+          "local_path": "index.html"
+      }
+  },
+  "description": "a sample description",
+  "origin": "app://app.id",
+  "icons": {
+    "144": "icons/icon_144.png",
+    "96": "icons/icon_96.png",
+    "72": "icons/icon_72.png",
+    "48": "icons/icon_48.png"
+  },
+  "default_locale": "en",
+  "fullscreen":"true"
+}
index a3edb37..c02ece3 100644 (file)
@@ -13,6 +13,7 @@
       <include name="IDR_XWALK_APPLICATION_EVENT_API" file="extension/application_event_api.js" type="BINDATA" />
       <include name="IDR_XWALK_APPLICATION_RUNTIME_API" file="extension/application_runtime_api.js" type="BINDATA" />
       <include name="IDR_XWALK_APPLICATION_WIDGET_API" file="extension/application_widget_api.js" type="BINDATA" />
+      <include name="IDR_XWALK_APPLICATION_WIDGET_COMMON_API" file="extension/application_widget_common_api.js" type="BINDATA" />
       <include name="IDR_XWALK_APPLICATION_TEST_API" file="test/application_testapi.js" type="BINDATA" />
     </includes>
   </release>
index 940a4fd..79e654e 100644 (file)
 #include "xwalk/application/common/application_manifest_constants.h"
 #include "xwalk/application/common/constants.h"
 #include "xwalk/application/common/manifest_handlers/main_document_handler.h"
+#include "xwalk/application/common/manifest_handlers/warp_handler.h"
 #include "xwalk/application/common/event_names.h"
 #include "xwalk/runtime/browser/runtime.h"
 #include "xwalk/runtime/browser/runtime_context.h"
 #include "xwalk/runtime/browser/xwalk_runner.h"
+#include "xwalk/runtime/common/xwalk_common_messages.h"
 
 namespace xwalk {
 
@@ -39,6 +41,11 @@ const char* kDefaultWidgetEntryPage[] = {
 "index.svg",
 "index.xhtml",
 "index.xht"};
+
+content::RenderProcessHost* GetHost(Runtime* runtime) {
+  DCHECK(runtime);
+  return runtime->web_contents()->GetRenderProcessHost();
+}
 }  // namespace
 
 namespace application {
@@ -97,6 +104,7 @@ bool Application::Launch(const LaunchParams& launch_params) {
     return false;
 
   main_runtime_ = Runtime::Create(runtime_context_, this);
+  InitSecurityPolicy();
   main_runtime_->LoadURL(url);
   if (entry_point_used_ != AppMainKey) {
     NativeAppWindow::CreateParams params;
@@ -382,5 +390,46 @@ bool Application::SetPermission(PermissionType type,
   return false;
 }
 
+void Application::InitSecurityPolicy() {
+  if (application_data_->GetPackageType() != Manifest::TYPE_WGT)
+    return;
+  const WARPInfo* info = static_cast<WARPInfo*>(
+      application_data_->GetManifestData(widget_keys::kAccessKey));
+  if (!info
+#if defined(OS_TIZEN)
+      // On Tizen, CSP mode has higher priority, and WARP will be disabled
+      // if the application is under CSP mode.
+      || application_data_->HasCSPDefined()
+#endif
+      )
+    return;
+  GURL app_url = application_data_->URL();
+  const base::ListValue* whitelist = info->GetWARP();
+  bool enable_warp_mode = true;
+  for (base::ListValue::const_iterator it = whitelist->begin();
+       it != whitelist->end(); ++it) {
+    base::DictionaryValue* value = NULL;
+    (*it)->GetAsDictionary(&value);
+    std::string dest;
+    if (!value || !value->GetString(widget_keys::kAccessOriginKey, &dest) ||
+        dest.empty())
+      continue;
+    if (dest == "*") {
+      enable_warp_mode = false;
+      break;
+    }
+
+    GURL dest_url(dest);
+    // The default subdomains attrubute should be "false".
+    std::string subdomains = "false";
+    value->GetString(widget_keys::kAccessSubdomainsKey, &subdomains);
+    GetHost(main_runtime_)->Send(
+        new ViewMsg_SetAccessWhiteList(
+            app_url, dest_url, (subdomains == "true")));
+  }
+  if (enable_warp_mode)
+    GetHost(main_runtime_)->Send(new ViewMsg_EnableWarpMode());
+}
+
 }  // namespace application
 }  // namespace xwalk
index e0f2662..f928494 100644 (file)
@@ -155,6 +155,8 @@ class Application : public Runtime::Observer {
   bool IsOnSuspendHandlerRegistered() const;
   bool IsTerminating() const { return finish_observer_; }
 
+  void InitSecurityPolicy();
+
   RuntimeContext* runtime_context_;
   const scoped_refptr<ApplicationData> application_data_;
   Runtime* main_runtime_;
index a2ee3f0..1469114 100644 (file)
@@ -11,6 +11,7 @@
 #include "base/file_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
 #include "base/version.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
@@ -26,6 +27,7 @@
 #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/installer/tizen/service_package_installer.h"
@@ -187,6 +189,16 @@ bool CopyDirectoryContents(const base::FilePath& from,
   return true;
 }
 
+void RemoveWidgetStorageFiles(const base::FilePath& storage_path,
+                              const std::string& app_id) {
+  base::FileEnumerator iter(storage_path, true,
+                            base::FileEnumerator::FILES);
+  for (base::FilePath file = iter.Next(); !file.empty(); file = iter.Next()) {
+    if (file.MaybeAsASCII().find(app_id) != std::string::npos)
+      base::DeleteFile(file, false);
+  }
+}
+
 }  // namespace
 
 const base::FilePath::CharType kApplicationsDir[] =
@@ -462,6 +474,10 @@ bool ApplicationService::Uninstall(const std::string& id) {
       application->URL(),
       partition->GetURLRequestContext());
 
+  base::FilePath path;
+  PathService::Get(xwalk::DIR_WGT_STORAGE_PATH, &path);
+  RemoveWidgetStorageFiles(path, id);
+
   FOR_EACH_OBSERVER(Observer, observers_, OnApplicationUninstalled(id));
 
   return result;
@@ -499,6 +515,7 @@ Application* ApplicationService::Launch(
 
 Application* ApplicationService::Launch(
     const std::string& id, const Application::LaunchParams& params) {
+  Application* application = NULL;
   scoped_refptr<ApplicationData> application_data =
     application_storage_->GetApplicationData(id);
   if (!application_data) {
@@ -506,11 +523,17 @@ Application* ApplicationService::Launch(
     return NULL;
   }
 
-  return Launch(application_data, params);
+  if ((application = Launch(application_data, params))) {
+    scoped_refptr<Event> event = Event::CreateEvent(
+        kOnLaunched, scoped_ptr<base::ListValue>(new base::ListValue));
+    event_manager_->SendEvent(application->id(), event);
+  }
+  return application;
 }
 
 Application* ApplicationService::Launch(
     const base::FilePath& path, const Application::LaunchParams& params) {
+  Application* application = NULL;
   if (!base::DirectoryExists(path))
     return NULL;
 
@@ -524,7 +547,12 @@ Application* ApplicationService::Launch(
     return NULL;
   }
 
-  return Launch(application_data, params);
+  if ((application = Launch(application_data, params))) {
+    scoped_refptr<Event> event = Event::CreateEvent(
+        kOnLaunched, scoped_ptr<base::ListValue>(new base::ListValue));
+    event_manager_->SendEvent(application->id(), event);
+  }
+  return application;
 }
 
 namespace {
index 098ab66..bfc9ce3 100644 (file)
@@ -126,9 +126,7 @@ bool ApplicationSystem::LaunchWithCommandLineParam(
   if (cmd_line.HasSwitch(switches::kFullscreen))
     launch_params.window_state = ui::SHOW_STATE_FULLSCREEN;
 
-  if (Application* application =
-      application_service_->Launch(param, launch_params)) {
-    event_manager_->SendEvent(application->id(), event);
+  if (application_service_->Launch(param, launch_params)) {
     return true;
   }
 
@@ -162,7 +160,7 @@ bool ApplicationSystem::LaunchWithCommandLineParam<GURL>(
   if (!application_data) {
     LOG(ERROR) << "Error occurred while trying to launch application: "
                << error;
-    return NULL;
+    return false;
   }
 
   Application::LaunchParams launch_params;
index 4f73dcd..46285a5 100644 (file)
@@ -18,7 +18,8 @@ namespace application {
 
 Package::Package(const base::FilePath& source_path)
     : source_path_(source_path),
-      is_extracted_(false) {
+      is_extracted_(false),
+      is_valid_(false) {
 }
 
 Package::~Package() {
@@ -46,11 +47,6 @@ bool Package::Extract(base::FilePath* target_path) {
     return true;
   }
 
-  if (!IsValid()) {
-    LOG(ERROR) << "XPK/WGT file is not valid.";
-    return false;
-  }
-
   if (!CreateTempDirectory()) {
     LOG(ERROR) << "Can't create a temporary"
                   "directory for extracting the package content.";
index fe58b98..c946844 100644 (file)
@@ -29,7 +29,7 @@ class 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|.
-  bool Extract(base::FilePath* target_path);
+  virtual bool Extract(base::FilePath* target_path);
  protected:
   explicit Package(const base::FilePath& source_path);
   scoped_ptr<ScopedStdioHandle> file_;
index 9816abe..9ce643d 100644 (file)
@@ -55,6 +55,8 @@ WGTPackage::WGTPackage(const base::FilePath& path)
   if (!value.empty())
     id_ = GenerateId(value);
 
+  is_valid_ = true;
+
   scoped_ptr<ScopedStdioHandle> file(
         new ScopedStdioHandle(base::OpenFile(path, "rb")));
 
@@ -63,6 +65,3 @@ WGTPackage::WGTPackage(const base::FilePath& path)
 
 }  // namespace application
 }  // namespace xwalk
-
-
-
index 22cdb33..7c084ac 100644 (file)
@@ -88,5 +88,19 @@ bool XPKPackage::VerifySignature() {
   return true;
 }
 
+bool XPKPackage::Extract(base::FilePath* target_path) {
+  if (is_extracted_) {
+    *target_path = temp_dir_.path();
+    return true;
+  }
+
+  if (!IsValid()) {
+    LOG(ERROR) << "The XPK file is not valid.";
+    return false;
+  }
+
+  return Package::Extract(target_path);
+}
+
 }  // namespace application
 }  // namespace xwalk
index 8b96e2f..c7a32a4 100644 (file)
@@ -30,6 +30,7 @@ class XPKPackage : public Package {
   };
   virtual ~XPKPackage();
   explicit XPKPackage(const base::FilePath& path);
+  virtual bool Extract(base::FilePath* target_path);
 
  private:
   // verify the signature in the xpk package
index dea676d..aeec0c1 100644 (file)
@@ -137,7 +137,10 @@ const std::string& ApplicationData::ID() const {
 }
 
 const std::string ApplicationData::VersionString() const {
-  return Version()->GetString();
+  if (!version_->components().empty())
+    return Version()->GetString();
+
+  return "";
 }
 
 bool ApplicationData::IsPlatformApp() const {
@@ -360,5 +363,13 @@ PermissionSet ApplicationData::GetManifestPermissions() const {
   return permissions;
 }
 
+#if defined(OS_TIZEN)
+bool ApplicationData::HasCSPDefined() const {
+  return (manifest_->HasPath(widget_keys::kCSPKey) ||
+          manifest_->HasPath(widget_keys::kCSPReportOnlyKey) ||
+          manifest_->HasPath(widget_keys::kAllowNavigationKey));
+}
+#endif
+
 }   // namespace application
 }   // namespace xwalk
index 34612ee..28d732c 100644 (file)
@@ -134,6 +134,10 @@ class ApplicationData : public base::RefCountedThreadSafe<ApplicationData> {
   bool HasMainDocument() const;
   Manifest::PackageType GetPackageType() const;
 
+#if defined(OS_TIZEN)
+  bool HasCSPDefined() const;
+#endif
+
  private:
   friend class base::RefCountedThreadSafe<ApplicationData>;
   friend class ApplicationStorageImpl;
index 22f90e1..b0795df 100644 (file)
@@ -13,6 +13,7 @@ const char kAppMainScriptsKey[] = "app.main.scripts";
 const char kAppMainSourceKey[] = "app.main.source";
 const char kCSPKey[] = "content_security_policy";
 const char kDescriptionKey[] = "description";
+const char kDisplay[] = "display";
 const char kLaunchLocalPathKey[] = "app.launch.local_path";
 const char kLaunchScreen[] = "launch_screen";
 const char kLaunchScreenReadyWhen[] = "launch_screen.ready_when";
@@ -33,6 +34,7 @@ const char kIcon128Key[] = "icons.128";
 
 // manifest keys for widget applications.
 namespace application_widget_keys {
+const char kNamespaceKey[] = "@namespace";
 const char kNameKey[] = "widget.name.#text";
 const char kVersionKey[] = "widget.@version";
 const char kWidgetKey[] = "widget";
@@ -61,10 +63,23 @@ const char kAccessSubdomainsKey[] = "@subdomains";
 
 #if defined(OS_TIZEN)
 const char kIcon128Key[] = "widget.icon.@src";
+const char kTizenApplicationKey[] = "widget.application";
+// Child keys inside 'kTizenApplicationKey'
+const char kTizenApplicationIdKey[] = "@id";
+const char kTizenApplicationPackageKey[] = "@package";
+const char kTizenApplicationRequiredVersionKey[] = "@required_version";
+
 const char kTizenAppIdKey[] = "widget.application.@package";
+const char kAllowNavigationKey[] = "widget.allow-navigation.#text";
+const char kCSPReportOnlyKey[] =
+    "widget.content-security-policy-report-only.#text";
 #endif
 }  // namespace application_widget_keys
 
+#if defined(OS_TIZEN)
+const char kTizenNamespacePrefix[] = "http://tizen.org/ns/widgets";
+#endif
+
 namespace application_manifest_errors {
 const char kInvalidDescription[] =
     "Invalid value for 'description'.";
index 59f5444..406c0dd 100644 (file)
@@ -15,6 +15,7 @@ namespace application_manifest_keys {
   extern const char kAppMainSourceKey[];
   extern const char kCSPKey[];
   extern const char kDescriptionKey[];
+  extern const char kDisplay[];
   extern const char kLaunchLocalPathKey[];
   extern const char kLaunchScreen[];
   extern const char kLaunchScreenReadyWhen[];
@@ -33,6 +34,7 @@ namespace application_manifest_keys {
 }  // namespace application_manifest_keys
 
 namespace application_widget_keys {
+  extern const char kNamespaceKey[];
   extern const char kNameKey[];
   extern const char kLaunchLocalPathKey[];
   extern const char kWebURLsKey[];
@@ -55,11 +57,21 @@ namespace application_widget_keys {
   extern const char kPreferencesValueKey[];
   extern const char kPreferencesReadonlyKey[];
 #if defined(OS_TIZEN)
+  extern const char kTizenApplicationKey[];
+  extern const char kTizenApplicationIdKey[];
+  extern const char kTizenApplicationPackageKey[];
+  extern const char kTizenApplicationRequiredVersionKey[];
   extern const char kTizenAppIdKey[];
   extern const char kIcon128Key[];
+  extern const char kAllowNavigationKey[];
+  extern const char kCSPReportOnlyKey[];
 #endif
 }  // namespace application_widget_keys
 
+#if defined(OS_TIZEN)
+extern const char kTizenNamespacePrefix[];
+#endif
+
 namespace application_manifest_errors {
   extern const char kInvalidDescription[];
   extern const char kInvalidKey[];
index c7395c2..d1b3e32 100644 (file)
@@ -9,6 +9,10 @@
 #include "base/stl_util.h"
 #include "xwalk/application/common/manifest_handlers/csp_handler.h"
 #include "xwalk/application/common/manifest_handlers/main_document_handler.h"
+#if defined(OS_TIZEN)
+#include "xwalk/application/common/manifest_handlers/navigation_handler.h"
+#include "xwalk/application/common/manifest_handlers/tizen_application_handler.h"
+#endif
 #include "xwalk/application/common/manifest_handlers/permissions_handler.h"
 #include "xwalk/application/common/manifest_handlers/warp_handler.h"
 #include "xwalk/application/common/manifest_handlers/widget_handler.h"
@@ -71,6 +75,8 @@ ManifestHandlerRegistry::GetInstanceForWGT() {
   handlers.push_back(new WARPHandler);
 #if defined(OS_TIZEN)
   handlers.push_back(new CSPHandler(Manifest::TYPE_WGT));
+  handlers.push_back(new NavigationHandler);
+  handlers.push_back(new TizenApplicationHandler);
 #endif
   widget_registry_ = new ManifestHandlerRegistry(handlers);
   return widget_registry_;
diff --git a/src/xwalk/application/common/manifest_handlers/navigation_handler.cc b/src/xwalk/application/common/manifest_handlers/navigation_handler.cc
new file mode 100644 (file)
index 0000000..3a75474
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/application/common/manifest_handlers/navigation_handler.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "xwalk/application/common/application_manifest_constants.h"
+
+namespace xwalk {
+
+namespace keys = application_widget_keys;
+
+namespace application {
+namespace {
+const char navigation_separator = ' ';
+}
+
+NavigationInfo::NavigationInfo(const std::string& allowed_domains) {
+  base::SplitString(allowed_domains, navigation_separator, &allowed_domains_);
+}
+
+NavigationInfo::~NavigationInfo() {
+}
+
+NavigationHandler::NavigationHandler() {
+}
+
+NavigationHandler::~NavigationHandler() {
+}
+
+bool NavigationHandler::Parse(scoped_refptr<ApplicationData> application_data,
+                              base::string16* error) {
+  if (!application_data->GetManifest()->HasPath(keys::kAllowNavigationKey))
+    return true;
+  std::string allowed_domains;
+  if (!application_data->GetManifest()->GetString(keys::kAllowNavigationKey,
+                                                  &allowed_domains)) {
+    *error = base::ASCIIToUTF16("Invalid value of allow-navigation.");
+    return false;
+  }
+  if (allowed_domains.empty())
+    return true;
+
+  application_data->SetManifestData(keys::kAllowNavigationKey,
+                                    new NavigationInfo(allowed_domains));
+
+  return true;
+}
+
+std::vector<std::string> NavigationHandler::Keys() const {
+  return std::vector<std::string>(1, keys::kAllowNavigationKey);
+}
+
+}  // namespace application
+}  // namespace xwalk
diff --git a/src/xwalk/application/common/manifest_handlers/navigation_handler.h b/src/xwalk/application/common/manifest_handlers/navigation_handler.h
new file mode 100644 (file)
index 0000000..c643382
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_NAVIGATION_HANDLER_H_
+#define XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_NAVIGATION_HANDLER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_split.h"
+#include "xwalk/application/common/application_data.h"
+#include "xwalk/application/common/manifest_handler.h"
+
+namespace xwalk {
+namespace application {
+
+class NavigationInfo : public ApplicationData::ManifestData {
+ public:
+  explicit NavigationInfo(const std::string& allowed_domains);
+  virtual ~NavigationInfo();
+
+  const std::vector<std::string>& GetAllowedDomains() const {
+    return allowed_domains_; }
+
+ private:
+  std::vector<std::string> allowed_domains_;
+};
+
+class NavigationHandler : public ManifestHandler {
+ public:
+  NavigationHandler();
+  virtual ~NavigationHandler();
+
+  virtual bool Parse(scoped_refptr<ApplicationData> application_data,
+                     base::string16* error) OVERRIDE;
+  virtual std::vector<std::string> Keys() const OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NavigationHandler);
+};
+
+}  // namespace application
+}  // namespace xwalk
+
+#endif  // XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_NAVIGATION_HANDLER_H_
diff --git a/src/xwalk/application/common/manifest_handlers/navigation_handler_unittest.cc b/src/xwalk/application/common/manifest_handlers/navigation_handler_unittest.cc
new file mode 100644 (file)
index 0000000..fc7aab4
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/application/common/manifest_handlers/navigation_handler.h"
+
+#include <string>
+#include <vector>
+#include "xwalk/application/common/application_manifest_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace xwalk {
+
+namespace keys = application_widget_keys;
+
+namespace application {
+
+class NavigationHandlerTest: public testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    manifest.SetString(keys::kNameKey, "no name");
+    manifest.SetString(keys::kVersionKey, "0");
+  }
+
+  scoped_refptr<ApplicationData> CreateApplication() {
+    std::string error;
+    scoped_refptr<ApplicationData> application = ApplicationData::Create(
+        base::FilePath(), Manifest::INVALID_TYPE, manifest, "", &error);
+    return application;
+  }
+
+  const NavigationInfo* GetNavigationInfo(
+      scoped_refptr<ApplicationData> application) {
+    const NavigationInfo* info = static_cast<NavigationInfo*>(
+        application->GetManifestData(keys::kAllowNavigationKey));
+    return info;
+  }
+
+  base::DictionaryValue manifest;
+};
+
+TEST_F(NavigationHandlerTest, NoNavigation) {
+  scoped_refptr<ApplicationData> application = CreateApplication();
+  EXPECT_TRUE(application.get());
+  EXPECT_FALSE(GetNavigationInfo(application));
+}
+
+TEST_F(NavigationHandlerTest, OneNavigation) {
+  manifest.SetString(keys::kAllowNavigationKey, "http://www.sample.com");
+  scoped_refptr<ApplicationData> application = CreateApplication();
+  EXPECT_TRUE(application.get());
+  EXPECT_EQ(application->GetPackageType(), Manifest::TYPE_WGT);
+  const NavigationInfo* info = GetNavigationInfo(application);
+  EXPECT_TRUE(info);
+  const std::vector<std::string>& list = info->GetAllowedDomains();
+  EXPECT_TRUE(list.size() == 1 && list[0] == "http://www.sample.com");
+}
+
+TEST_F(NavigationHandlerTest, Navigations) {
+  manifest.SetString(keys::kAllowNavigationKey,
+                     "http://www.sample1.com www.sample2.com");
+  scoped_refptr<ApplicationData> application = CreateApplication();
+  EXPECT_TRUE(application.get());
+  EXPECT_EQ(application->GetPackageType(), Manifest::TYPE_WGT);
+  const NavigationInfo* info = GetNavigationInfo(application);
+  EXPECT_TRUE(info);
+  const std::vector<std::string>& list = info->GetAllowedDomains();
+  EXPECT_TRUE(list.size() == 2 &&
+              list[0] == "http://www.sample1.com" &&
+              list[1] == "www.sample2.com");
+}
+
+}  // namespace application
+}  // namespace xwalk
diff --git a/src/xwalk/application/common/manifest_handlers/tizen_application_handler.cc b/src/xwalk/application/common/manifest_handlers/tizen_application_handler.cc
new file mode 100644 (file)
index 0000000..1eab83c
--- /dev/null
@@ -0,0 +1,119 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/application/common/manifest_handlers/tizen_application_handler.h"
+
+#include <map>
+#include <utility>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/strings/string_split.h"
+#include "third_party/re2/re2/re2.h"
+#include "xwalk/application/common/application_manifest_constants.h"
+
+namespace xwalk {
+
+namespace keys = application_widget_keys;
+
+namespace application {
+
+TizenApplicationInfo::TizenApplicationInfo() {
+}
+
+TizenApplicationInfo::~TizenApplicationInfo() {
+}
+
+TizenApplicationHandler::TizenApplicationHandler() {}
+
+TizenApplicationHandler::~TizenApplicationHandler() {}
+
+bool TizenApplicationHandler::Parse(scoped_refptr<ApplicationData> application,
+                                    base::string16* error) {
+  scoped_ptr<TizenApplicationInfo> app_info(new TizenApplicationInfo);
+  const Manifest* manifest = application->GetManifest();
+  DCHECK(manifest);
+
+  base::Value* app_value = NULL;
+  manifest->Get(keys::kTizenApplicationKey, &app_value);
+  // Find an application element with tizen namespace
+  base::DictionaryValue* app_dict;
+  std::string value;
+  bool find = false;
+  if (app_value && app_value->IsType(base::Value::TYPE_DICTIONARY)) {
+    app_value->GetAsDictionary(&app_dict);
+    find = app_dict->GetString(keys::kNamespaceKey, &value);
+    find = find && (value == kTizenNamespacePrefix);
+  } else if (app_value && app_value->IsType(base::Value::TYPE_LIST)) {
+    base::ListValue* list;
+    app_value->GetAsList(&list);
+    for (base::ListValue::iterator it = list->begin();
+         it != list->end(); ++it) {
+      (*it)->GetAsDictionary(&app_dict);
+      find = app_dict->GetString(keys::kNamespaceKey, &value);
+      find = find && (value == kTizenNamespacePrefix);
+      if (find)
+        break;
+    }
+  }
+
+  if (!find) {
+    *error = base::ASCIIToUTF16(
+        "Cannot find application element with tizen namespace"
+        " or the tizen namespace prefix is incorrect.\n");
+    return false;
+  }
+  if (app_dict->GetString(keys::kTizenApplicationIdKey, &value))
+    app_info->set_id(value);
+  if (app_dict->GetString(keys::kTizenApplicationPackageKey, &value))
+    app_info->set_package(value);
+  if (app_dict->GetString(keys::kTizenApplicationRequiredVersionKey, &value))
+    app_info->set_required_version(value);
+
+  application->SetManifestData(keys::kTizenApplicationKey,
+                               app_info.release());
+  return true;
+}
+
+bool TizenApplicationHandler::Validate(
+    scoped_refptr<const ApplicationData> application,
+    std::string* error,
+    std::vector<InstallWarning>* warnings) const {
+  const TizenApplicationInfo* app_info =
+      static_cast<const TizenApplicationInfo*>(
+          application->GetManifestData(keys::kTizenApplicationKey));
+
+  const char kIdPattern[] = "\\A[0-9a-zA-Z]{10}[.][0-9a-zA-Z]{1,52}\\z";
+  const char kPackagePattern[] = "\\A[0-9a-zA-Z]{10}\\z";
+  if (!RE2::PartialMatch(app_info->id(), kIdPattern)) {
+    *error = std::string("The id property of application element"
+                         " does not match the format\n");
+    return false;
+  }
+  if (!RE2::PartialMatch(app_info->package(), kPackagePattern)) {
+    *error = std::string("The package property of application element"
+                         " does not match the format\n");
+    return false;
+  }
+  if (app_info->id().find(app_info->package()) != 0) {
+    *error = std::string("The application element property id"
+                         " does not start with package.\n");
+    return false;
+  }
+  // TODO(hongzhang): We need a version map (Tizen API version
+  // to Crosswalk API version) for checking required_version
+  if (app_info->required_version().empty()) {
+    *error = std::string("The required_version property of application"
+                         " element does not exist.\n");
+    return false;
+  }
+
+  return true;
+}
+
+std::vector<std::string> TizenApplicationHandler::Keys() const {
+  return std::vector<std::string>(1, keys::kTizenApplicationKey);
+}
+
+}  // namespace application
+}  // namespace xwalk
diff --git a/src/xwalk/application/common/manifest_handlers/tizen_application_handler.h b/src/xwalk/application/common/manifest_handlers/tizen_application_handler.h
new file mode 100644 (file)
index 0000000..ef45c23
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_TIZEN_APPLICATION_HANDLER_H_
+#define XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_TIZEN_APPLICATION_HANDLER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/values.h"
+#include "xwalk/application/common/application_data.h"
+#include "xwalk/application/common/manifest_handler.h"
+
+namespace xwalk {
+namespace application {
+
+class TizenApplicationInfo : public ApplicationData::ManifestData {
+ public:
+  TizenApplicationInfo();
+  virtual ~TizenApplicationInfo();
+
+  void set_id(const std::string& id) {
+    id_ = id;
+  }
+  void set_package(const std::string& package) {
+    package_ = package;
+  }
+  void set_required_version(
+      const std::string& required_version) {
+    required_version_ = required_version;
+  }
+  const std::string& id() const {
+    return id_;
+  }
+  const std::string& package() const {
+    return package_;
+  }
+  const std::string& required_version() const {
+    return required_version_;
+  }
+
+ private:
+  std::string id_;
+  std::string package_;
+  std::string required_version_;
+};
+
+class TizenApplicationHandler : public ManifestHandler {
+ public:
+  TizenApplicationHandler();
+  virtual ~TizenApplicationHandler();
+
+  virtual bool Parse(scoped_refptr<ApplicationData> application,
+                     base::string16* error) OVERRIDE;
+  virtual bool Validate(scoped_refptr<const ApplicationData> application,
+                        std::string* error,
+                        std::vector<InstallWarning>* warnings) const OVERRIDE;
+  virtual std::vector<std::string> Keys() const OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TizenApplicationHandler);
+};
+
+}  // namespace application
+}  // namespace xwalk
+
+#endif  // XWALK_APPLICATION_COMMON_MANIFEST_HANDLERS_TIZEN_APPLICATION_HANDLER_H_
index dd3cfc7..ee49846 100644 (file)
@@ -71,8 +71,9 @@ void ParsePreferenceItem(const base::DictionaryValue* in_value,
   if (in_value->GetString(keys::kPreferencesValueKey, &pref_value))
     out_value->SetString(kPreferencesValue, pref_value);
 
-  if (in_value->GetString(keys::kPreferencesReadonlyKey, &pref_readonly))
-    out_value->SetString(kPreferencesReadonly, pref_readonly);
+  if (in_value->GetString(keys::kPreferencesReadonlyKey, &pref_readonly)) {
+      out_value->SetBoolean(kPreferencesReadonly, pref_readonly == "true");
+  }
 }
 
 }  // namespace
diff --git a/src/xwalk/application/common/manifest_handlers/widget_handler_unittest.cc b/src/xwalk/application/common/manifest_handlers/widget_handler_unittest.cc
new file mode 100644 (file)
index 0000000..6fecbdd
--- /dev/null
@@ -0,0 +1,219 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/application/common/manifest_handlers/widget_handler.h"
+
+#include "xwalk/application/common/application_manifest_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace xwalk {
+
+namespace keys = application_widget_keys;
+
+namespace application {
+
+namespace {
+// Below key names are readable from Javascript widget interface.
+const char kWidgetAuthor[] = "author";
+const char kWidgetDecription[] = "description";
+const char kWidgetName[] = "name";
+const char kWidgetShortName[] = "shortName";
+const char kWidgetVersion[] = "version";
+const char kWidgetID[] = "id";
+const char kWidgetAuthorEmail[] = "authorEmail";
+const char kWidgetAuthorHref[] = "authorHref";
+const char kWidgetHeight[] = "height";
+const char kWidgetWidth[] = "width";
+const char kWidgetPreferences[] = "preferences";
+
+// Child keys inside 'preferences' key.
+const char kWidgetPreferencesName[] = "name";
+const char kWidgetPreferencesValue[] = "value";
+const char kWidgetPreferencesReadonly[] = "readonly";
+
+// Value to test
+const char author[] = "Some one";
+const char decription[] = "This is a test";
+const char name[] = "widget handler unittest";
+const char shortName[] = "whu";
+const char version[] = "0.0.0.1";
+const char ID[] = "iiiiiiiiiid";
+const char authorEmail[] = "aaa@bbb.com";
+const char authorHref[] = "http://www.ssss.com";
+const char height[] = "800";
+const char width[] = "480";
+
+const char* preferencesName[] = {"pname0", "pname1", "pname2"};
+const char* preferencesValue[] = {"pvalue0", "pvalue1", "pvalue2"};
+const char* preferencesReadonly[] = {"true", "false", "false"};
+}  // namespace
+
+class WidgetHandlerTest: public testing::Test {
+ public:
+  scoped_refptr<ApplicationData> CreateApplication(
+    base::DictionaryValue &manifest) {
+    std::string error;
+    scoped_refptr<ApplicationData> application = ApplicationData::Create(
+        base::FilePath(), Manifest::INVALID_TYPE, manifest, "", &error);
+    return application;
+  }
+
+  WidgetInfo* GetWidgetInfo(scoped_refptr<ApplicationData> application) {
+    WidgetInfo* info = static_cast<WidgetInfo*>(
+      application->GetManifestData(keys::kWidgetKey));
+    return info;
+  }
+
+  base::DictionaryValue* GetPreferencesItem(int id,
+                                            bool is_parsed_manifest_key) {
+    base::DictionaryValue* preferences = new base::DictionaryValue;
+    if (is_parsed_manifest_key) {
+      preferences->SetString(keys::kPreferencesNameKey,
+                             preferencesName[id]);
+      preferences->SetString(keys::kPreferencesValueKey,
+                             preferencesValue[id]);
+      // PreferencesReadonly is string on manifest and bool on widgetInfo
+      preferences->SetString(keys::kPreferencesReadonlyKey,
+                             preferencesReadonly[id]);
+    } else {
+      preferences->SetString(kWidgetPreferencesName,
+                             preferencesName[id]);
+      preferences->SetString(kWidgetPreferencesValue,
+                             preferencesValue[id]);
+      preferences->SetBoolean(kWidgetPreferencesReadonly,
+                              strncmp(preferencesReadonly[id], "true", 4) == 0);
+    }
+    return preferences;
+  }
+
+  // No Preferences and full other information
+  void SetAllInfoToManifest(base::DictionaryValue* manifest) {
+    // Insert some key-value pairs into manifest use full key
+    manifest->SetString(keys::kAuthorKey,      author);
+    manifest->SetString(keys::kDescriptionKey, decription);
+    manifest->SetString(keys::kNameKey,        name);
+    manifest->SetString(keys::kShortNameKey,   shortName);
+    manifest->SetString(keys::kVersionKey,     version);
+    manifest->SetString(keys::kIDKey,          ID);
+    manifest->SetString(keys::kAuthorEmailKey, authorEmail);
+    manifest->SetString(keys::kAuthorHrefKey,  authorHref);
+    manifest->SetString(keys::kHeightKey,      height);
+    manifest->SetString(keys::kWidthKey,       width);
+  }
+
+  // No Preferences and full other information
+  void SetAllInfoToWidget(base::DictionaryValue* widget) {
+    // Insert some key-value pairs into widget use widget key;
+    widget->SetString(kWidgetAuthor,      author);
+    widget->SetString(kWidgetDecription,  decription);
+    widget->SetString(kWidgetName,        name);
+    widget->SetString(kWidgetShortName,   shortName);
+    widget->SetString(kWidgetVersion,     version);
+    widget->SetString(kWidgetID,          ID);
+    widget->SetString(kWidgetAuthorEmail, authorEmail);
+    widget->SetString(kWidgetAuthorHref,  authorHref);
+    widget->SetString(kWidgetHeight,      height);
+    widget->SetString(kWidgetWidth,       width);
+  }
+};
+
+TEST_F(WidgetHandlerTest, ParseManifestWithOnlyNameAndVersion) {
+  base::DictionaryValue manifest;
+  manifest.SetString(keys::kNameKey, "no name");
+  manifest.SetString(keys::kVersionKey, "0");
+
+  scoped_refptr<ApplicationData> application = CreateApplication(manifest);
+  EXPECT_TRUE(application);
+
+  WidgetInfo* info = GetWidgetInfo(application);
+  int size = info->GetWidgetInfo()->size();
+
+  // Only name and version ,others are empty string "",but exist.
+  // And widget have 10 items.
+  EXPECT_EQ(size, 10);
+
+  base::DictionaryValue* widget = info->GetWidgetInfo();
+  base::DictionaryValue::Iterator it(*widget);
+
+  std::string tmpStr;
+  // Check value
+  while (!it.IsAtEnd()) {
+    it.value().GetAsString(&tmpStr);
+    if (it.key() == kWidgetName) {
+      EXPECT_EQ(tmpStr, "no name");
+    } else if (it.key() == kWidgetVersion) {
+      EXPECT_EQ(tmpStr, "0");
+    } else {
+      EXPECT_EQ(tmpStr, "");
+    }
+    it.Advance();
+  }
+}
+
+TEST_F(WidgetHandlerTest,
+       ParseManifestWithAllOfOtherItemsAndOnePreferenceItem) {
+  // Create a manifest with one preference item.
+  scoped_ptr<base::DictionaryValue> manifest(new base::DictionaryValue);
+  SetAllInfoToManifest(manifest.get());
+  manifest->Set(keys::kPreferencesKey, GetPreferencesItem(0, true));
+  // Create an application use this manifest.
+  scoped_refptr<ApplicationData> application;
+  application = CreateApplication(*(manifest.get()));
+  EXPECT_TRUE(application);
+  EXPECT_EQ(application->GetPackageType(), Manifest::TYPE_WGT);
+  // Get widget info from this application.
+  WidgetInfo* info = GetWidgetInfo(application);
+  EXPECT_TRUE(info);
+  scoped_ptr<base::DictionaryValue> Copy(info->GetWidgetInfo()->DeepCopy());
+  base::DictionaryValue* widget_parsed_from_manifest;
+  Copy->GetAsDictionary(&widget_parsed_from_manifest);
+  EXPECT_TRUE(widget_parsed_from_manifest);
+
+  // Create a widget with one preference item manually.
+  scoped_ptr<base::DictionaryValue> widget(new base::DictionaryValue);
+  SetAllInfoToWidget(widget.get());
+  widget->Set(kWidgetPreferences, GetPreferencesItem(0, false));
+
+  // Compare the widget parsed from manifest with
+  // the widget create manually.
+  EXPECT_TRUE(widget->Equals(widget_parsed_from_manifest));
+}
+
+TEST_F(WidgetHandlerTest,
+       ParseManifestWithAllOfOtherItemsAndThreePreferenceItemsList) {
+  // Create a manifest with three preference items.
+  scoped_ptr<base::DictionaryValue> manifest(new base::DictionaryValue);
+  SetAllInfoToManifest(manifest.get());
+  base::ListValue* manifestPreferences = new base::ListValue;
+  for (int i = 0; i < 3; i++) {
+    manifestPreferences->Append(GetPreferencesItem(i, true));
+  }
+  // Create an application use this manifest,
+  scoped_refptr<ApplicationData> application;
+  application = CreateApplication(*(manifest.get()));
+  EXPECT_TRUE(application);
+  EXPECT_EQ(application->GetPackageType(), Manifest::TYPE_WGT);
+  // Get widget info from this application.
+  WidgetInfo* info = GetWidgetInfo(application);
+  EXPECT_TRUE(info);
+  scoped_ptr<base::DictionaryValue> Copy(info->GetWidgetInfo()->DeepCopy());
+  base::DictionaryValue* widget_parsed_from_manifest;
+  Copy->GetAsDictionary(&widget_parsed_from_manifest);
+  EXPECT_TRUE(widget_parsed_from_manifest);
+
+  // Create a widget with three preference items manually.
+  scoped_ptr<base::DictionaryValue> widget(new base::DictionaryValue);
+  SetAllInfoToWidget(widget.get());
+  base::ListValue* widgetPreferences   = new base::ListValue;
+  for (int i = 0; i < 3; i++) {
+    widgetPreferences->Append(GetPreferencesItem(i, false));
+  }
+
+  // Compare the widget parsed from manifest with
+  // the widget create manually.
+  EXPECT_TRUE(widget->Equals(widget_parsed_from_manifest));
+}
+
+}  // namespace application
+}  // namespace xwalk
index 1675c9a..bbc9933 100644 (file)
@@ -3,9 +3,11 @@
 // found in the LICENSE file.
 
 var application = requireNative('application');
+var common = requireNative('widget_common');
 
 var empty = "";
 var zero = 0;
+
 var widgetStringInfo = {
   "author"      : empty,
   "description" : empty,
@@ -29,7 +31,8 @@ function defineReadOnlyProperty(object, key, value) {
       } else if (key == "height") {
         value = window.innerHeight;
       } else if (value == empty) {
-        value = extension.internal.sendSyncMessage(key);
+        value = extension.internal.sendSyncMessage(
+            { cmd: 'GetWidgetInfo', widgetKey: key });
       }
 
       return value;
@@ -41,3 +44,94 @@ for (var key in widgetStringInfo) {
   defineReadOnlyProperty(exports, key, widgetStringInfo[key]);
 }
 
+var WidgetStorage = function() {
+  var _keyList = new Array();
+
+  this.init = function() {
+    var result = extension.internal.sendSyncMessage(
+        { cmd: 'GetAllItems' });
+    for (var itemKey in result) {
+      var itemValue = result[itemKey];
+      this[itemKey] = itemValue;
+      _keyList.push(itemKey);
+    }
+  }
+
+  this.__defineGetter__('length', function() {
+    return _keyList.length;
+  });
+
+  this.key = function(index) {
+    return _keyList[index];
+  }
+
+  this.getItem = function(itemKey) {
+    return this[String(itemKey)];
+  } 
+
+  this.setItem = function(itemKey, itemValue) {
+    var result = extension.internal.sendSyncMessage({
+        cmd: 'SetPreferencesItem',
+        preferencesItemKey: String(itemKey),
+        preferencesItemValue: String(itemValue) });
+
+    if (result) {
+      this[String(itemKey)] = String(itemValue);
+      _keyList.push(String(itemKey));
+    } else {
+      throw new common.CustomDOMException(
+          common.CustomDOMException.NO_MODIFICATION_ALLOWED_ERR,
+          'The object can not be modified.');
+    }
+  };
+  
+  this.removeItem = function(itemKey) {
+    var result = extension.internal.sendSyncMessage({
+        cmd: 'RemovePreferencesItem',
+        preferencesItemKey: String(itemKey) });
+
+    if (result) {
+      delete this[itemKey];
+      delete _keyList[_keyList.indexOf(String(itemKey))];
+    } else {
+      throw new common.CustomDOMException(
+          common.CustomDOMException.NO_MODIFICATION_ALLOWED_ERR,
+          'The object can not be modified.');
+    }
+  }
+
+  this.clear = function() {
+    var itemKey;
+    var result = extension.internal.sendSyncMessage({
+        cmd: 'ClearAllItems' });
+
+    if (!result)
+      return;
+
+    for (var i = _keyList.length-1; i >= 0; --i) {
+      // if the itemKey is still in DB(e.g. readonly),
+      // we should keep it in JS side.
+      var exists = extension.internal.sendSyncMessage({
+          cmd: 'KeyExists',
+          preferencesItemKey: _keyList[i] });
+
+      if (!exists) {
+        delete this[_keyList[i]];
+        _keyList.splice(i, 1);
+      }
+    }
+  }
+
+  this.init();
+};
+
+var widgetStorage = new WidgetStorage();
+exports.preferences = widgetStorage;
+
+Object.defineProperty(exports, 'preferences', {
+  configurable: false,
+  enumerable: false,
+  get: function() {
+    return widgetStorage;
+  }
+});
diff --git a/src/xwalk/application/extension/application_widget_common_api.js b/src/xwalk/application/extension/application_widget_common_api.js
new file mode 100644 (file)
index 0000000..60a1599
--- /dev/null
@@ -0,0 +1,82 @@
+var errors = {
+  '1': { type: 'INDEX_SIZE_ERR', name: 'IndexSizeError', message: '' },
+  '2': { type: 'DOMSTRING_SIZE_ERR', name: 'DOMStringSizeError', message: '' },
+  '3': { type: 'HIERARCHY_REQUEST_ERR', name: 'HierarchyRequestError', message: '' },
+  '4': { type: 'WRONG_DOCUMENT_ERR', name: 'WrongDocumentError', message: '' },
+  '5': { type: 'INVALID_CHARACTER_ERR', name: 'InvalidCharacterError', message: '' },
+  '6': { type: 'NO_DATA_ALLOWED_ERR', name: 'NoDataAllowedError', message: '' },
+  '7': { type: 'NO_MODIFICATION_ALLOWED_ERR', name: 'NoModificationAllowedError', message: '' },
+  '8': { type: 'NOT_FOUND_ERR', name: 'NotFoundError', message: '' },
+  '9': { type: 'NOT_SUPPORTED_ERR', name: 'Not_supportedError', message: '' },
+  '10': { type: 'INUSE_ATTRIBUTE_ERR', name: 'InuseAttributeError', message: '' },
+  '11': { type: 'INVALID_STATE_ERR', name: 'InvalidStateError', message: '' },
+  '12': { type: 'SYNTAX_ERR', name: 'SyntaxError', message: '' },
+  '13': { type: 'INVALID_MODIFICATION_ERR', name: 'InvalidModificationError', message: '' },
+  '14': { type: 'NAMESPACE_ERR', name: 'NamespaceError', message: '' },
+  '15': { type: 'INVALID_ACCESS_ERR', name: 'InvalidAccessError', message: '' },
+  '16': { type: 'VALIDATION_ERR', name: 'ValidationError', message: '' },
+  '17': { type: 'TYPE_MISMATCH_ERR', name: 'TypeMismatchError', message: '' },
+  '18': { type: 'SECURITY_ERR', name: 'SecurityError', message: '' },
+  '19': { type: 'NETWORK_ERR', name: 'NetworkError', message: '' },
+  '20': { type: 'ABORT_ERR', name: 'AbortError', message: '' },
+  '21': { type: 'URL_MISMATCH_ERR', name: 'UrlMismatchError', message: '' },
+  '22': { type: 'QUOTA_EXCEEDED_ERR', name: 'QuotaExceededError', message: '' },
+  '23': { type: 'TIMEOUT_ERR', name: 'TimeoutError', message: '' },
+  '24': { type: 'INVALID_NODE_TYPE_ERR', name: 'InvalidNodeTypeError', message: '' },
+  '25': { type: 'DATA_CLONE_ERR', name: 'DataCloneError', message: '' },
+};
+
+var CustomDOMException = function(code, message) {
+  var _code, _message, _name;
+
+  if (typeof code !== 'number') {
+    throw TypeError('Wrong argument type for Exception.');
+  } else if ((code in errors) === false) {
+    throw TypeError('Unknown exception code: ' + code);
+  } else {
+    _code = code;
+    _name = errors[_code].name;
+    if (typeof message === 'string') {
+      _message = message;
+    } else {
+      _message = errors[_code].message;
+    }
+  }
+
+  var props = {};
+  var newException;
+
+  try {
+    document.removeChild({})
+  } catch (e) {
+    newException = Object.create(e)
+  }
+
+  var proto = newException.__proto__;
+
+  props = Object.getOwnPropertyDescriptor(proto, "name");
+  props.value = _name;
+  Object.defineProperty(newException, "name", props);
+
+  props = Object.getOwnPropertyDescriptor(proto, "code");
+  props.value = _code;
+  Object.defineProperty(newException, "code", props);
+
+  props = Object.getOwnPropertyDescriptor(proto, "message");
+  props.value = _message;
+  Object.defineProperty(newException, "message", props);
+
+  props.value = function() {
+    return _name + ": " + _message;
+  }
+  Object.defineProperty(newException, "toString", props);
+
+  return newException;
+}
+
+for (var value in errors) {
+  Object.defineProperty(CustomDOMException, errors[value].type,
+      { value: parseInt(value) });
+}
+
+exports.CustomDOMException = CustomDOMException;
index 3b671a3..8db16b7 100644 (file)
@@ -5,6 +5,8 @@
 #include "xwalk/application/extension/application_widget_extension.h"
 
 #include "base/bind.h"
+#include "base/path_service.h"
+#include "base/strings/string_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "ipc/ipc_message.h"
 #include "xwalk/application/common/application_data.h"
 #include "xwalk/application/common/application_manifest_constants.h"
 #include "xwalk/application/common/manifest_handlers/widget_handler.h"
+#include "xwalk/application/extension/application_widget_storage.h"
 #include "xwalk/runtime/browser/runtime.h"
+#include "xwalk/runtime/browser/runtime_context.h"
+#include "xwalk/runtime/browser/xwalk_runner.h"
+#include "xwalk/runtime/common/xwalk_paths.h"
 
 using content::BrowserThread;
 
+namespace {
+const char kCommandKey[] = "cmd";
+const char kWidgetAttributeKey[] = "widgetKey";
+const char kPreferencesItemKey[] = "preferencesItemKey";
+const char kPreferencesItemValue[] = "preferencesItemValue";
+}
+
 namespace xwalk {
 namespace application {
 
@@ -37,36 +50,154 @@ XWalkExtensionInstance* ApplicationWidgetExtension::CreateInstance() {
 
 AppWidgetExtensionInstance::AppWidgetExtensionInstance(
     Application* application)
-  : application_(application) {
+  : application_(application),
+    handler_(this) {
   DCHECK(application_);
+  base::ThreadRestrictions::SetIOAllowed(true);
+
+  base::FilePath path;
+  xwalk::RegisterPathProvider();
+  PathService::Get(xwalk::DIR_WGT_STORAGE_PATH, &path);
+  widget_storage_.reset(new AppWidgetStorage(application_, path));
 }
 
+AppWidgetExtensionInstance::~AppWidgetExtensionInstance() {}
+
 void AppWidgetExtensionInstance::HandleMessage(scoped_ptr<base::Value> msg) {
+  handler_.HandleMessage(msg.Pass());
 }
 
 void AppWidgetExtensionInstance::HandleSyncMessage(
     scoped_ptr<base::Value> msg) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  std::string key;
-  base::Value* result;
-  base::StringValue* ret_val = base::Value::CreateStringValue("");
+  base::DictionaryValue* dict;
+  std::string command;
+  msg->GetAsDictionary(&dict);
 
-  if (!msg->GetAsString(&key)) {
-    LOG(ERROR) << "Fail to get sync message as manifest widget key.";
-    SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
+  if (!msg->GetAsDictionary(&dict) || !dict->GetString(kCommandKey, &command)) {
+    LOG(ERROR) << "Fail to handle command sync message.";
+    SendSyncReplyToJS(scoped_ptr<base::Value>(
+        base::Value::CreateStringValue("")));
     return;
   }
 
+  scoped_ptr<base::Value> result(base::Value::CreateStringValue(""));
+  if (command == "GetWidgetInfo") {
+    result = GetWidgetInfo(msg.Pass());
+  } else if (command == "SetPreferencesItem") {
+    result = SetPreferencesItem(msg.Pass());
+  } else if (command == "RemovePreferencesItem") {
+    result = RemovePreferencesItem(msg.Pass());
+  } else if (command == "ClearAllItems") {
+    result = ClearAllItems(msg.Pass());
+  } else if (command == "GetAllItems") {
+    result = GetAllItems(msg.Pass());
+  } else if (command == "KeyExists") {
+    result = KeyExists(msg.Pass());
+  } else {
+    LOG(ERROR) << command << " ASSERT NOT REACHED.";
+  }
+
+  SendSyncReplyToJS(result.Pass());
+}
+
+scoped_ptr<base::StringValue> AppWidgetExtensionInstance::GetWidgetInfo(
+    scoped_ptr<base::Value> msg) {
+  scoped_ptr<base::StringValue> result(base::Value::CreateStringValue(""));
+  std::string key;
+  std::string value;
+  base::DictionaryValue* dict;
+
+  if (!msg->GetAsDictionary(&dict) ||
+      !dict->GetString(kWidgetAttributeKey, &key)) {
+    LOG(ERROR) << "Fail to get widget attribute key.";
+    return result.Pass();
+  }
+
   WidgetInfo* info =
       static_cast<WidgetInfo*>(
       application_->data()->GetManifestData(widget_keys::kWidgetKey));
-  base::DictionaryValue* value = info->GetWidgetInfo();
-  if (!value->Get(key, &result)) {
-    LOG(ERROR) << "Fail to get value for key: " << key;
-    SendSyncReplyToJS(scoped_ptr<base::Value>(ret_val));
-  } else {
-    SendSyncReplyToJS(scoped_ptr<base::Value>(result));
+  base::DictionaryValue* widget_info = info->GetWidgetInfo();
+  widget_info->GetString(key, &value);
+  result.reset(base::Value::CreateStringValue(value));
+  return result.Pass();
+}
+
+scoped_ptr<base::FundamentalValue>
+AppWidgetExtensionInstance::SetPreferencesItem(scoped_ptr<base::Value> msg) {
+  scoped_ptr<base::FundamentalValue> result(
+      base::Value::CreateBooleanValue(false));
+  std::string key;
+  std::string value;
+  base::DictionaryValue* dict;
+
+  if (!msg->GetAsDictionary(&dict) ||
+      !dict->GetString(kPreferencesItemKey, &key) ||
+      !dict->GetString(kPreferencesItemValue, &value)) {
+    LOG(ERROR) << "Fail to set preferences item.";
+    return result.Pass();
+  }
+
+  if (widget_storage_->AddEntry(key, value, false))
+    result.reset(base::Value::CreateBooleanValue(true));
+
+  return result.Pass();
+}
+
+scoped_ptr<base::FundamentalValue>
+AppWidgetExtensionInstance::RemovePreferencesItem(scoped_ptr<base::Value> msg) {
+  scoped_ptr<base::FundamentalValue> result(
+      base::Value::CreateBooleanValue(false));
+  std::string key;
+  base::DictionaryValue* dict;
+
+  if (!msg->GetAsDictionary(&dict) ||
+      !dict->GetString(kPreferencesItemKey, &key)) {
+    LOG(ERROR) << "Fail to remove preferences item.";
+    return result.Pass();
   }
+
+  if (widget_storage_->RemoveEntry(key))
+    result.reset(base::Value::CreateBooleanValue(true));
+
+  return result.Pass();
+}
+
+scoped_ptr<base::FundamentalValue> AppWidgetExtensionInstance::ClearAllItems(
+    scoped_ptr<base::Value> msg) {
+  scoped_ptr<base::FundamentalValue> result(
+      base::Value::CreateBooleanValue(false));
+
+  if (widget_storage_->Clear())
+    result.reset(base::Value::CreateBooleanValue(true));
+
+  return result.Pass();
+}
+
+scoped_ptr<base::DictionaryValue> AppWidgetExtensionInstance::GetAllItems(
+    scoped_ptr<base::Value> msg) {
+  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
+  widget_storage_->GetAllEntries(result.get());
+
+  return result.Pass();
+}
+
+scoped_ptr<base::FundamentalValue> AppWidgetExtensionInstance::KeyExists(
+    scoped_ptr<base::Value> msg) const {
+  scoped_ptr<base::FundamentalValue> result(
+      base::Value::CreateBooleanValue(false));
+  std::string key;
+  base::DictionaryValue* dict;
+
+  if (!msg->GetAsDictionary(&dict) ||
+      !dict->GetString(kPreferencesItemKey, &key)) {
+    LOG(ERROR) << "Fail to remove preferences item.";
+    return result.Pass();
+  }
+
+  if (widget_storage_->EntryExists(key))
+    result.reset(base::Value::CreateBooleanValue(true));
+
+  return result.Pass();
 }
 
 }  // namespace application
index 25afa99..b37ddc4 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "xwalk/extensions/browser/xwalk_extension_function_handler.h"
 #include "xwalk/extensions/common/xwalk_extension.h"
 
 namespace xwalk {
@@ -14,6 +15,8 @@ namespace application {
 class Application;
 
 using extensions::XWalkExtension;
+using extensions::XWalkExtensionFunctionHandler;
+using extensions::XWalkExtensionFunctionInfo;
 using extensions::XWalkExtensionInstance;
 
 class ApplicationWidgetExtension : public XWalkExtension {
@@ -30,12 +33,25 @@ class ApplicationWidgetExtension : public XWalkExtension {
 class AppWidgetExtensionInstance : public XWalkExtensionInstance {
  public:
   explicit AppWidgetExtensionInstance(Application* application);
+  virtual ~AppWidgetExtensionInstance();
 
   virtual void HandleMessage(scoped_ptr<base::Value> msg) OVERRIDE;
   virtual void HandleSyncMessage(scoped_ptr<base::Value> msg) OVERRIDE;
 
  private:
+  scoped_ptr<base::StringValue> GetWidgetInfo(scoped_ptr<base::Value> msg);
+  scoped_ptr<base::FundamentalValue> SetPreferencesItem(
+      scoped_ptr<base::Value> mgs);
+  scoped_ptr<base::FundamentalValue> RemovePreferencesItem(
+      scoped_ptr<base::Value> mgs);
+  scoped_ptr<base::FundamentalValue> ClearAllItems(scoped_ptr<base::Value> mgs);
+  scoped_ptr<base::DictionaryValue> GetAllItems(scoped_ptr<base::Value> mgs);
+  scoped_ptr<base::FundamentalValue> KeyExists(
+      scoped_ptr<base::Value> mgs) const;
+
   Application* application_;
+  scoped_ptr<class AppWidgetStorage> widget_storage_;
+  XWalkExtensionFunctionHandler handler_;
 };
 
 }  // namespace application
diff --git a/src/xwalk/application/extension/application_widget_storage.cc b/src/xwalk/application/extension/application_widget_storage.cc
new file mode 100644 (file)
index 0000000..70895a3
--- /dev/null
@@ -0,0 +1,306 @@
+// 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/extension/application_widget_storage.h"
+
+#include <string>
+
+#include "base/file_util.h"
+#include "sql/statement.h"
+#include "sql/transaction.h"
+#include "xwalk/application/common/application_manifest_constants.h"
+#include "xwalk/application/common/manifest_handlers/widget_handler.h"
+
+namespace {
+
+namespace widget_keys = xwalk::application_widget_keys;
+
+const char kPreferences[] = "preferences";
+const char kPreferencesName[] = "name";
+const char kPreferencesValue[] = "value";
+const char kPreferencesReadonly[] = "readonly";
+
+const base::FilePath::CharType kWidgetStorageExtension[] =
+    FILE_PATH_LITERAL(".widgetStorage");
+
+const char kStorageTableName[] = "widget_storage";
+
+const char kCreateStorageTableOp[] =
+    "CREATE TABLE widget_storage ("
+    "key TEXT NOT NULL UNIQUE PRIMARY KEY,"
+    "value TEXT NOT NULL,"
+    "read_only INTEGER )";
+
+const char kClearStorageTableWithBindOp[] =
+    "DELETE FROM widget_storage WHERE read_only = ? ";
+
+const char kInsertItemWithBindOp[] =
+    "INSERT INTO widget_storage (value, read_only, key) "
+    "VALUES(?,?,?)";
+
+const char kUpdateItemWithBindOp[] =
+    "UPDATE widget_storage SET value = ? , read_only = ? "
+    "WHERE key = ?";
+
+const char kRemoveItemWithBindOp[] =
+    "DELETE FROM widget_storage WHERE key = ?";
+
+const char kSelectTableLength[] =
+    "SELECT count(*) FROM widget_storage ";
+
+const char kSelectCountWithBindOp[] =
+    "SELECT count(*) FROM widget_storage "
+    "WHERE key = ?";
+
+const char kSelectAllItem[] =
+    "SELECT key, value FROM widget_storage ";
+
+const char kSelectReadOnlyWithBindOp[] =
+    "SELECT read_only FROM widget_storage "
+    "WHERE key = ?";
+}  // namespace
+
+namespace xwalk {
+namespace application {
+
+AppWidgetStorage::AppWidgetStorage(Application* application,
+                                   const base::FilePath& data_dir)
+    : application_(application),
+      db_initialized_(false) {
+  sqlite_db_.reset(new sql::Connection);
+
+  base::FilePath name(application_->id());
+  base::FilePath::StringType storage_name =
+      name.value() + kWidgetStorageExtension;
+  data_path_ = data_dir.Append(storage_name);
+
+  if (!base::PathExists(data_dir) && !base::CreateDirectory(data_dir)) {
+    LOG(ERROR) << "Could not create widget storage path.";
+    return;
+  }
+
+  if (!Init()) {
+    LOG(ERROR) << "Initialize widget storage failed.";
+    return;
+  }
+}
+
+AppWidgetStorage::~AppWidgetStorage() {
+}
+
+bool AppWidgetStorage::Init() {
+  if (!sqlite_db_->Open(data_path_)) {
+    LOG(ERROR) << "Unable to open widget storage DB.";
+    return false;
+  }
+  sqlite_db_->Preload();
+
+  if (!InitStorageTable()) {
+     LOG(ERROR) << "Unable to init widget storage table.";
+     return false;
+  }
+  return db_initialized_;
+}
+
+bool AppWidgetStorage::SaveConfigInfoItem(base::DictionaryValue* dict) {
+  DCHECK(dict);
+  std::string key;
+  std::string value;
+  bool read_only = false;
+  dict->GetString(kPreferencesName, &key);
+  dict->GetString(kPreferencesValue, &value);
+  dict->GetBoolean(kPreferencesReadonly, &read_only);
+  return AddEntry(key, value, read_only);
+}
+
+bool AppWidgetStorage::SaveConfigInfoInDB() {
+  WidgetInfo* info =
+      static_cast<WidgetInfo*>(
+      application_->data()->GetManifestData(widget_keys::kWidgetKey));
+  base::DictionaryValue* widget_info = info->GetWidgetInfo();
+  if (!widget_info) {
+    LOG(ERROR) << "Fail to get parsed widget information.";
+    return false;
+  }
+
+  base::Value* pref_value;
+  widget_info->Get(kPreferences, &pref_value);
+
+  if (pref_value && pref_value->IsType(base::Value::TYPE_DICTIONARY)) {
+    base::DictionaryValue* dict;
+    pref_value->GetAsDictionary(&dict);
+    return SaveConfigInfoItem(dict);
+  } else if (pref_value && pref_value->IsType(base::Value::TYPE_LIST)) {
+    base::ListValue* list;
+    pref_value->GetAsList(&list);
+
+    for (base::ListValue::iterator it = list->begin();
+         it != list->end(); ++it) {
+      base::DictionaryValue* dict;
+      (*it)->GetAsDictionary(&dict);
+      if (!SaveConfigInfoItem(dict))
+        return false;
+    }
+  } else {
+    LOG(INFO) << "No widget preferences or preference type is not supported.";
+  }
+
+  return true;
+}
+
+bool AppWidgetStorage::InitStorageTable() {
+  if (sqlite_db_->DoesTableExist(kStorageTableName)) {
+    db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
+    return true;
+  }
+
+  sql::Transaction transaction(sqlite_db_.get());
+  transaction.Begin();
+  if (!sqlite_db_->Execute(kCreateStorageTableOp))
+    return false;
+  if (!transaction.Commit())
+    return false;
+
+  db_initialized_ = (sqlite_db_ && sqlite_db_->is_open());
+  SaveConfigInfoInDB();
+
+  return true;
+}
+
+bool AppWidgetStorage::EntryExists(const std::string& key) const {
+  sql::Transaction transaction(sqlite_db_.get());
+  if (!transaction.Begin())
+    return false;
+
+  sql::Statement stmt(sqlite_db_->GetUniqueStatement(
+      kSelectCountWithBindOp));
+  stmt.BindString(0, key);
+  if (!stmt.Step()) {
+    LOG(ERROR) << "An error occured when selecting count from DB.";
+    return false;
+  }
+
+  if (!transaction.Commit())
+    return false;
+
+  int exist = stmt.ColumnInt(0);
+  return exist > 0;
+}
+
+bool AppWidgetStorage::IsReadOnly(const std::string& key) {
+  sql::Transaction transaction(sqlite_db_.get());
+  if (!transaction.Begin())
+    return true;
+
+  sql::Statement stmt(sqlite_db_->GetUniqueStatement(
+      kSelectReadOnlyWithBindOp));
+  stmt.BindString(0, key);
+  if (!stmt.Step()) {
+    LOG(ERROR) << "An error occured when selecting count from DB.";
+    return true;
+  }
+
+  if (!transaction.Commit())
+    return true;
+
+  return stmt.ColumnBool(0);
+}
+
+bool AppWidgetStorage::AddEntry(const std::string& key,
+                               const std::string& value,
+                               bool read_only) {
+  if (!db_initialized_ && !Init())
+    return false;
+
+  std::string operation;
+  if (!EntryExists(key)) {
+    operation = kInsertItemWithBindOp;
+  } else if (!IsReadOnly(key)) {
+    operation = kUpdateItemWithBindOp;
+  } else {
+    LOG(ERROR) << "Could not set read only item " << key;
+    return false;
+  }
+
+  sql::Transaction transaction(sqlite_db_.get());
+  if (!transaction.Begin())
+    return false;
+
+  sql::Statement stmt(sqlite_db_->GetUniqueStatement(
+    operation.c_str()));
+  stmt.BindString(0, value);
+  stmt.BindBool(1, read_only);
+  stmt.BindString(2, key);
+  if (!stmt.Run()) {
+    LOG(ERROR) << "An error occured when set item into DB.";
+    return false;
+  }
+
+  return transaction.Commit();
+}
+
+bool AppWidgetStorage::RemoveEntry(const std::string& key) {
+  if (!db_initialized_ && !Init())
+    return false;
+
+  if (IsReadOnly(key)) {
+    LOG(ERROR) << "Could not remove read only item " << key;
+    return false;
+  }
+
+  sql::Transaction transaction(sqlite_db_.get());
+  if (!transaction.Begin())
+    return false;
+
+  sql::Statement stmt(sqlite_db_->GetUniqueStatement(
+      kRemoveItemWithBindOp));
+  stmt.BindString(0, key);
+
+  if (!stmt.Run()) {
+    LOG(ERROR) << "An error occured when removing item into DB.";
+    return false;
+  }
+
+  return transaction.Commit();
+}
+
+bool AppWidgetStorage::Clear() {
+  if (!db_initialized_ && !Init())
+    return false;
+
+  sql::Transaction transaction(sqlite_db_.get());
+  transaction.Begin();
+
+  sql::Statement stmt(sqlite_db_->GetUniqueStatement(
+      kClearStorageTableWithBindOp));
+  stmt.BindBool(0, false);
+
+  if (!stmt.Run()) {
+    LOG(ERROR) << "An error occured when removing item into DB.";
+    return false;
+  }
+
+  return transaction.Commit();
+}
+
+bool AppWidgetStorage::GetAllEntries(base::DictionaryValue* result) {
+  std::string key;
+  std::string value;
+  DCHECK(result);
+
+  if (!db_initialized_ && !Init())
+    return false;
+
+  sql::Statement stmt(sqlite_db_->GetUniqueStatement(kSelectAllItem));
+  while (stmt.Step()) {
+    key = stmt.ColumnString(0);
+    value = stmt.ColumnString(1);
+    result->SetString(key, value);
+  }
+
+  return true;
+}
+
+}  // namespace application
+}  // namespace xwalk
diff --git a/src/xwalk/application/extension/application_widget_storage.h b/src/xwalk/application/extension/application_widget_storage.h
new file mode 100644 (file)
index 0000000..ad83ed6
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_APPLICATION_EXTENSION_APPLICATION_WIDGET_STORAGE_H_
+#define XWALK_APPLICATION_EXTENSION_APPLICATION_WIDGET_STORAGE_H_
+
+#include <map>
+#include <string>
+
+#include "base/values.h"
+#include "base/files/file_path.h"
+#include "sql/connection.h"
+#include "xwalk/application/browser/application.h"
+
+namespace xwalk {
+namespace application {
+
+class AppWidgetStorage {
+ public:
+  AppWidgetStorage(Application* application,
+                   const base::FilePath& data_dir);
+  ~AppWidgetStorage();
+
+  // Adds or replaces entry (if not readonly);
+  // returns true on success.
+  bool AddEntry(const std::string& key,
+               const std::string& value,
+               bool read_only);
+  bool RemoveEntry(const std::string& key);
+  bool Clear();
+  bool GetAllEntries(base::DictionaryValue* result);
+  bool EntryExists(const std::string& key) const;
+
+ private:
+  bool Init();
+  bool IsReadOnly(const std::string& key);
+  bool InitStorageTable();
+  bool SaveConfigInfoInDB();
+  bool SaveConfigInfoItem(base::DictionaryValue* dict);
+
+  Application* application_;
+  scoped_ptr<sql::Connection> sqlite_db_;
+  base::FilePath data_path_;
+  bool db_initialized_;
+};
+
+}  // namespace application
+}  // namespace xwalk
+#endif  // XWALK_APPLICATION_EXTENSION_APPLICATION_WIDGET_STORAGE_H_
index dd5e09a..af8551f 100644 (file)
@@ -25,11 +25,26 @@ static const char* xwalk_running_manager_iface =
 static const char* xwalk_running_app_iface =
     "org.crosswalkproject.Running.Application1";
 
-static const char cmd_line_fullscreen_arg[] = "--fullscreen";
-
 static char* application_object_path;
 
 static GMainLoop* mainloop;
+static GDBusConnection* g_connection;
+
+static int g_argc;
+static char** g_argv;
+static gboolean query_running = FALSE;
+static gboolean fullscreen = FALSE;
+static gchar** cmd_appid;
+
+static GOptionEntry entries[] = {
+  { "running", 'r', 0, G_OPTION_ARG_NONE, &query_running,
+    "Check whether the application is running", NULL },
+  { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen,
+    "Run the application as fullscreen", NULL },
+  { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &cmd_appid,
+    "ID of the application to be launched", NULL },
+  { NULL }
+};
 
 static void object_removed(GDBusObjectManager* manager, GDBusObject* object,
                            gpointer user_data) {
@@ -73,64 +88,52 @@ static void on_app_properties_changed(GDBusProxy* proxy,
   }
 }
 
-int main(int argc, char** argv) {
-  GError* error = NULL;
-  char* appid;
-  gboolean fullscreen = FALSE;
-
-
-#if !GLIB_CHECK_VERSION(2, 36, 0)
-  // g_type_init() is deprecated on GLib since 2.36, Tizen has 2.32.
-  g_type_init();
-#endif
-
-  if (xwalk_tizen_set_home_for_user_app())
-    exit(1);
-
-  if (!strcmp(basename(argv[0]), "xwalk-launcher")) {
-    if (argc < 2) {
-      fprintf(stderr, "No AppID informed, nothing to do\n");
-      exit(1);
-    }
-
-    appid = argv[1];
+static void query_application_running(GDBusObjectManager* running_om,
+                                      const char* app_id) {
+  GList* objects = g_dbus_object_manager_get_objects(running_om);
+  GList* it;
+  bool is_running = FALSE;
+
+  for (it = objects; it; it = it->next) {
+    GDBusObject* object = reinterpret_cast<GDBusObject*>(it->data);
+    GDBusInterface* iface = g_dbus_object_get_interface(
+        object,
+        xwalk_running_app_iface);
+    if (!iface)
+      continue;
 
-    if (argc > 2) {
-      if (!strcmp(basename(argv[2]), cmd_line_fullscreen_arg))
-        fullscreen = TRUE;
+    GDBusProxy* proxy = G_DBUS_PROXY(iface);
+    GVariant* id_variant;
+    id_variant = g_dbus_proxy_get_cached_property(proxy, "AppID");
+    if (!id_variant) {
+      g_object_unref(iface);
+      continue;
     }
 
-  } else {
-    appid = strdup(basename(argv[0]));
-
-    if (argc > 1) {
-      if (!strcmp(basename(argv[1]), cmd_line_fullscreen_arg))
-        fullscreen = TRUE;
+    const gchar* id;
+    g_variant_get(id_variant, "s", &id);
+    if (!strcmp(app_id, id)) {
+      is_running = TRUE;
+      break;
     }
-  }
 
-  GDBusConnection* connection = get_session_bus_connection(&error);
-  if (!connection) {
-    fprintf(stderr, "Couldn't get the session bus connection: %s\n",
-            error->message);
-    exit(1);
+    g_object_unref(iface);
   }
+  const char* str = is_running ? "running" : "not running";
+  g_print("Application %s is %s.\n", app_id, str);
 
-  GDBusObjectManager* running_apps_om = g_dbus_object_manager_client_new_sync(
-      connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
-      xwalk_service_name, xwalk_running_path,
-      NULL, NULL, NULL, NULL, &error);
-  if (!running_apps_om) {
-    fprintf(stderr, "Service '%s' does could not be reached: %s\n",
-            xwalk_service_name, error->message);
-    exit(1);
-  }
+  g_list_free_full(objects, g_object_unref);
+}
 
-  g_signal_connect(running_apps_om, "object-removed",
+static void launch_application(GDBusObjectManager* running_apps_manager,
+                               const char* appid,
+                               gboolean fullscreen) {
+  GError* error = NULL;
+  g_signal_connect(running_apps_manager, "object-removed",
                    G_CALLBACK(object_removed), NULL);
 
   GDBusProxy* running_proxy = g_dbus_proxy_new_sync(
-      connection,
+      g_connection,
       G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name,
       xwalk_running_path, xwalk_running_manager_iface, NULL, &error);
   if (!running_proxy) {
@@ -142,12 +145,9 @@ int main(int argc, char** argv) {
 
   unsigned int launcher_pid = getpid();
 
-  GVariant* result = g_dbus_proxy_call_sync(running_proxy, "Launch",
-                                            g_variant_new("(sub)", appid,
-                                                          launcher_pid,
-                                                          fullscreen),
-                                            G_DBUS_CALL_FLAGS_NONE,
-                                            -1, NULL, &error);
+  GVariant* result  = g_dbus_proxy_call_sync(running_proxy, "Launch",
+      g_variant_new("(sub)", appid, launcher_pid, fullscreen),
+      G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
   if (!result) {
     fprintf(stderr, "Couldn't call 'Launch' method: %s\n", error->message);
     exit(1);
@@ -158,7 +158,7 @@ int main(int argc, char** argv) {
           application_object_path);
 
   GDBusProxy* app_proxy = g_dbus_proxy_new_sync(
-      connection,
+      g_connection,
       G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name,
       application_object_path, xwalk_running_app_iface, NULL, &error);
   if (!app_proxy) {
@@ -177,13 +177,71 @@ int main(int argc, char** argv) {
   char name[128];
   snprintf(name, sizeof(name), "xwalk-%s", appid);
 
-  if (xwalk_appcore_init(argc, argv, name)) {
+  if (xwalk_appcore_init(g_argc, g_argv, name)) {
     fprintf(stderr, "Failed to initialize appcore");
     exit(1);
   }
 #endif
 
   g_main_loop_run(mainloop);
+}
+
+int main(int argc, char** argv) {
+  GError* error = NULL;
+  char* appid;
+
+  g_argc = argc;
+  g_argv = argv;
+
+#if !GLIB_CHECK_VERSION(2, 36, 0)
+  // g_type_init() is deprecated on GLib since 2.36.
+  g_type_init();
+#endif
+
+  if (xwalk_tizen_set_home_for_user_app())
+    exit(1);
+
+  GOptionContext* context =
+      g_option_context_new("- Crosswalk Application Launcher");
+  g_option_context_add_main_entries(context, entries, NULL);
+  if (!g_option_context_parse(context, &argc, &argv, &error)) {
+    fprintf(stderr, "Option parsing failed: %s\n", error->message);
+    exit(1);
+  }
+
+  if (!strcmp(basename(argv[0]), "xwalk-launcher")) {
+    if (cmd_appid == NULL) {
+      fprintf(stderr, "No AppID informed, nothing to do.\n");
+      return 0;
+    }
+    appid = cmd_appid[0];
+  } else {
+    appid = strdup(basename(argv[0]));
+  }
+
+  g_connection = get_session_bus_connection(&error);
+  if (!g_connection) {
+    fprintf(stderr, "Couldn't get the session bus connection: %s\n",
+            error->message);
+    exit(1);
+  }
+
+  GDBusObjectManager* running_apps_manager =
+      g_dbus_object_manager_client_new_sync(
+          g_connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+          xwalk_service_name, xwalk_running_path,
+          NULL, NULL, NULL, NULL, &error);
+  if (!running_apps_manager) {
+    fprintf(stderr, "Service '%s' does could not be reached: %s\n",
+            xwalk_service_name, error->message);
+    exit(1);
+  }
+
+  if (query_running) {
+    query_application_running(running_apps_manager, appid);
+  } else {
+    launch_application(running_apps_manager, appid, fullscreen);
+  }
 
   return 0;
 }
index 9be9a99..ae83293 100644 (file)
@@ -83,6 +83,8 @@
         'extension/application_runtime_extension.h',
         'extension/application_widget_extension.cc',
         'extension/application_widget_extension.h',
+        'extension/application_widget_storage.cc',
+        'extension/application_widget_storage.h',
 
         'renderer/application_native_module.cc',
         'renderer/application_native_module.h',
           'dependencies': [
             'build/system.gyp:tizen',
             'tizen/xwalk_tizen.gypi:xwalk_tizen_lib',
+            '../third_party/re2/re2.gyp:re2',
           ],
           'sources': [
             'browser/installer/tizen/packageinfo_constants.cc',
             'browser/installer/tizen/packageinfo_constants.h',
             'browser/installer/tizen/service_package_installer.cc',
             'browser/installer/tizen/service_package_installer.h',
+            'common/manifest_handlers/navigation_handler.cc',
+            'common/manifest_handlers/navigation_handler.h',
+            'common/manifest_handlers/tizen_application_handler.cc',
+            'common/manifest_handlers/tizen_application_handler.h',
           ],
         }],
       ],
index 27acabe..b2ddb98 100644 (file)
@@ -1,15 +1,5 @@
 {
   'variables': {
-    # Enable multitouch support with XInput2.1. When it is enabled, unlike
-    # XInput2.2, there are no XI_TouchBegin, XI_TouchUpdate and XI_TouchEnd
-    # raw touch events emitted from touch device. Instead, the touch event is
-    # simulated by a normal mouse event, since X server maintains multiple
-    # virtual touch screen devices as floating device, each of them can
-    # simulate a touch event tracked by the device id of event source, as a
-    # result, multi-touch support works with these simulated touch events
-    # dispatched from floating device.
-    'enable_xi21_mt%': 0,
-
     'tizen%': 0,
     'tizen_mobile%': 0,
   },
@@ -19,9 +9,6 @@
       'tizen_mobile%': '<(tizen_mobile)',
     },
     'conditions': [
-      ['enable_xi21_mt==1', {
-        'defines': ['ENABLE_XI21_MT=1'],
-      }],
       ['tizen==1', {
         'defines': ['OS_TIZEN=1'],
       }],
index 1401f37..d816137 100755 (executable)
@@ -41,12 +41,6 @@ sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'liblouis'))
 sys.path.insert(1, os.path.join(chrome_src, 'third_party', 'WebKit',
     'Source', 'build', 'scripts'))
 
-# FIXME(rakuco,joone): This is a workaround to allow the Tizen build to
-# proceed, as we use make there and GN isn't involved in this case (otherwise
-# we run into problems like GN always looking for GTK+ dependencies).
-if os.environ.get('GYP_GENERATORS') != 'make':
-  import find_depot_tools
-
 # On Windows, Psyco shortens warm runs of build/gyp_chromium by about
 # 20 seconds on a z600 machine with 12 GB of RAM, from 90 down to 70
 # seconds.  Conversely, memory usage of build/gyp_chromium with Psyco
@@ -373,6 +367,7 @@ if __name__ == '__main__':
   # TODO(bradnelson): take this out once this issue is fixed:
   #    http://code.google.com/p/gyp/issues/detail?id=177
   if sys.platform == 'cygwin':
+    import find_depot_tools
     depot_tools_path = find_depot_tools.add_depot_tools_to_path()
     python_dir = sorted(glob.glob(os.path.join(depot_tools_path,
                                                'python2*_bin')))[-1]
@@ -436,6 +431,7 @@ if __name__ == '__main__':
   # by depot_tools, then use it.
   if (sys.platform in ('win32', 'cygwin') and
       os.environ.get('GYP_GENERATORS') == 'ninja'):
+    import find_depot_tools
     depot_tools_path = find_depot_tools.add_depot_tools_to_path()
     toolchain = os.path.normpath(os.path.join(
         depot_tools_path, 'win_toolchain', 'vs2013_files'))
@@ -465,13 +461,6 @@ if __name__ == '__main__':
 
   supplemental_includes = GetSupplementalFiles()
 
-  # FIXME(rakuco,joone): This is a workaround to allow the Tizen build to
-  # proceed, as we use make there and GN isn't involved in this case (otherwise
-  # we run into problems like GN always looking for GTK+ dependencies).
-  if os.environ.get('GYP_GENERATORS') != 'make':
-    if not RunGN(supplemental_includes):
-      sys.exit(1)
-
   args.extend(
       ['-I' + i for i in additional_include_files(supplemental_includes, args)])
 
diff --git a/src/xwalk/packaging/crosswalk-2.31-enable-VAVDA-with-EGL.patch b/src/xwalk/packaging/crosswalk-2.31-enable-VAVDA-with-EGL.patch
deleted file mode 100644 (file)
index 6595561..0000000
+++ /dev/null
@@ -1,1313 +0,0 @@
-From c9f2fa16578bc20c83247e72608b5d6ca4dff6ba Mon Sep 17 00:00:00 2001
-From: "qing.zhang" <qing.zhang@intel.com>
-Date: Thu, 7 Nov 2013 08:59:38 -0500
-Subject: [PATCH] [Tizen] Enabling Hardware Acceleration with Libva and EGL in
-     VDA for Tizen Mobile within chromium v31+.
-
-Why we need to maintain it in our side:
-===========================================
-1) Upstream confirm VAVDA will continue to be restricted to
-   CrOS/X86 for dev & testing only and not for chromium road map.
-2) CrOS/X86 no plan to expend EGL backend which finalize in
-   June 2012 and be addressed to the CrOS graphics team.
-
-So, the upstream no plan to lerage VAVDA with EGL graphic
-   backend for any X86.
-
-3) The tizen-mobile's driver only support EGL as texture
-   backend. The video hw acceleration of xwalk have to
-   rely on EGL not GLX to bind decoded pixmap.
-===========================================
-That's why we enable specific EGL for VAVDA in tizen port.
----
- .../gpu/media/gpu_video_decode_accelerator.cc      |   8 +
- .../media/vaapi_video_decode_accelerator_tizen.cc  | 908 +++++++++++++++++++++
- .../media/vaapi_video_decode_accelerator_tizen.h   | 273 +++++++
- content/content_common.gypi                        |  26 +
- 4 files changed, 1215 insertions(+)
- create mode 100644 content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc
- create mode 100644 content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h
-
-diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc
-index bd1dc5f..c5a6df2 100644
---- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
-+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
-@@ -32,6 +32,8 @@
- #include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
- #include "ui/gl/gl_context_glx.h"
- #include "ui/gl/gl_implementation.h"
-+#elif defined(OS_TIZEN_MOBILE) && defined(ARCH_CPU_X86_FAMILY)
-+#include "content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h"
- #elif defined(OS_ANDROID)
- #include "content/common/gpu/media/android_video_decode_accelerator.h"
- #endif
-@@ -296,6 +298,12 @@ void GpuVideoDecodeAccelerator::Initialize(
-       static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext());
-   video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
-       glx_context->display(), this, make_context_current_));
-+#elif defined(OS_TIZEN_MOBILE) && defined(ARCH_CPU_X86_FAMILY)
-+  video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator(
-+      gfx::GLSurfaceEGL::GetHardwareDisplay(),
-+      stub_->decoder()->GetGLContext()->GetHandle(),
-+      this,
-+      make_context_current_));
- #elif defined(OS_ANDROID)
-   video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator(
-       this,
-diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc
-new file mode 100644
-index 0000000..cfff457
---- /dev/null
-+++ b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.cc
-@@ -0,0 +1,908 @@
-+// 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 "base/bind.h"
-+#include "base/debug/trace_event.h"
-+#include "base/logging.h"
-+#include "base/metrics/histogram.h"
-+#include "base/stl_util.h"
-+#include "base/strings/string_util.h"
-+#include "base/synchronization/waitable_event.h"
-+#include "content/child/child_thread.h"
-+#include "content/common/gpu/gpu_channel.h"
-+#include "content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h"
-+#include "media/base/bind_to_current_loop.h"
-+#include "media/video/picture.h"
-+#include "ui/gl/gl_bindings.h"
-+#include "ui/gl/scoped_binders.h"
-+
-+static void ReportToUMA(
-+    content::VaapiH264Decoder::VAVDAH264DecoderFailure failure) {
-+  UMA_HISTOGRAM_ENUMERATION(
-+      "Media.VAVDAH264.DecoderFailure",
-+      failure,
-+      content::VaapiH264Decoder::VAVDA_H264_DECODER_FAILURES_MAX);
-+}
-+
-+namespace content {
-+
-+#define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret)  \
-+  do {                                                              \
-+    if (!(result)) {                                                \
-+      DVLOG(1) << log;                                              \
-+      NotifyError(error_code);                                      \
-+      return ret;                                                   \
-+    }                                                               \
-+  } while (0)
-+
-+VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0), size(0) {
-+}
-+
-+VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {
-+}
-+
-+void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
-+  if (message_loop_ != base::MessageLoop::current()) {
-+    DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error));
-+    return;
-+  }
-+
-+  // Post Cleanup() as a task so we don't recursively acquire lock_.
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::Cleanup, weak_this_));
-+
-+  DVLOG(1) << "Notifying of error " << error;
-+  if (client_) {
-+    client_->NotifyError(error);
-+    client_ptr_factory_.InvalidateWeakPtrs();
-+  }
-+}
-+
-+// TFPPicture allocates X Pixmaps and binds them to textures passed
-+// in PictureBuffers from clients to them. TFPPictures are created as
-+// a consequence of receiving a set of PictureBuffers from clients and released
-+// at the end of decode (or when a new set of PictureBuffers is required).
-+//
-+// TFPPictures are used for output, contents of VASurfaces passed from decoder
-+// are put into the associated pixmap memory and sent to client.
-+class VaapiVideoDecodeAccelerator::TFPPicture {
-+ public:
-+  ~TFPPicture();
-+
-+  static linked_ptr<TFPPicture> Create(
-+      const base::Callback<bool(void)>& make_context_current,
-+      EGLDisplay egl_display,
-+      Display* x_display,
-+      int32 picture_buffer_id,
-+      uint32 texture_id,
-+      gfx::Size size);
-+  int32 picture_buffer_id() {
-+    return picture_buffer_id_;
-+  }
-+
-+  uint32 texture_id() {
-+    return texture_id_;
-+  }
-+
-+  gfx::Size size() {
-+    return size_;
-+  }
-+
-+  int x_pixmap() {
-+    return x_pixmap_;
-+  }
-+
-+  // Bind texture to pixmap. Needs to be called every frame.
-+  bool Bind();
-+
-+ private:
-+  TFPPicture(const base::Callback<bool(void)>& make_context_current,
-+             Display* x_display,
-+             int32 picture_buffer_id,
-+             uint32 texture_id,
-+             gfx::Size size);
-+
-+  bool Initialize(EGLDisplay egl_display);
-+
-+  base::Callback<bool(void)> make_context_current_;
-+
-+  Display* x_display_;
-+
-+  // Output id for the client.
-+  int32 picture_buffer_id_;
-+  uint32 texture_id_;
-+
-+  gfx::Size size_;
-+
-+  // Pixmaps bound to this texture.
-+  Pixmap x_pixmap_;
-+  EGLDisplay egl_display_;
-+  EGLImageKHR egl_image_;
-+
-+  DISALLOW_COPY_AND_ASSIGN(TFPPicture);
-+};
-+
-+VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
-+    const base::Callback<bool(void)>& make_context_current,
-+    Display* x_display,
-+    int32 picture_buffer_id,
-+    uint32 texture_id,
-+    gfx::Size size)
-+    : make_context_current_(make_context_current),
-+      x_display_(x_display),
-+      picture_buffer_id_(picture_buffer_id),
-+      texture_id_(texture_id),
-+      size_(size),
-+      x_pixmap_(0),
-+      egl_image_(0) {
-+  DCHECK(!make_context_current_.is_null());
-+};
-+
-+linked_ptr<VaapiVideoDecodeAccelerator::TFPPicture>
-+VaapiVideoDecodeAccelerator::TFPPicture::Create(
-+    const base::Callback<bool(void)>& make_context_current,
-+    EGLDisplay egl_display,
-+    Display* x_display,
-+    int32 picture_buffer_id,
-+    uint32 texture_id,
-+    gfx::Size size) {
-+
-+  linked_ptr<TFPPicture> tfp_picture(
-+    new TFPPicture(make_context_current, x_display,
-+                     picture_buffer_id, texture_id, size));
-+
-+  if (!tfp_picture->Initialize(egl_display))
-+    tfp_picture.reset();
-+
-+  return tfp_picture;
-+}
-+
-+bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
-+    EGLDisplay egl_display) {
-+  // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
-+  DCHECK(ChildThread::current() == NULL ||
-+      ChildThread::current()->message_loop() == base::MessageLoop::current());
-+
-+  if (!make_context_current_.Run())
-+    return false;
-+
-+  XWindowAttributes win_attr;
-+  int screen = DefaultScreen(x_display_);
-+  XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr);
-+  //TODO(posciak): pass the depth required by libva, not the RootWindow's depth
-+  x_pixmap_ = XCreatePixmap(x_display_, RootWindow(x_display_, screen),
-+                            size_.width(), size_.height(), win_attr.depth);
-+  if (!x_pixmap_) {
-+    DVLOG(1) << "Failed creating an X Pixmap for TFP";
-+    return false;
-+  }
-+
-+  egl_display_ = egl_display;
-+  EGLint image_attrs[] = { EGL_IMAGE_PRESERVED_KHR, 1 , EGL_NONE };
-+
-+  egl_image_ = eglCreateImageKHR(egl_display_,
-+                                EGL_NO_CONTEXT,
-+                                EGL_NATIVE_PIXMAP_KHR,
-+                                (EGLClientBuffer)x_pixmap_,
-+                                image_attrs);
-+  if (!egl_image_) {
-+    DVLOG(1) << "Failed creating a EGLImage from Pixmap for KHR";
-+    return false;
-+  }
-+
-+  return true;
-+}
-+VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
-+  // Check for NULL prevents unittests from crashing on non-existing ChildThread.
-+  DCHECK(ChildThread::current() == NULL ||
-+      ChildThread::current()->message_loop() == base::MessageLoop::current());
-+
-+  // Unbind surface from texture and deallocate resources.
-+  if (make_context_current_.Run()) {
-+      eglDestroyImageKHR(egl_display_, egl_image_);
-+  }
-+
-+  if (x_pixmap_)
-+    XFreePixmap(x_display_, x_pixmap_);
-+  XSync(x_display_, False);  // Needed to work around buggy vdpau-driver.
-+}
-+
-+bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
-+  DCHECK(x_pixmap_);
-+  DCHECK(egl_image_);
-+
-+  // Check for NULL prevents unittests from crashing on nonexistent ChildThread.
-+  DCHECK(ChildThread::current() == NULL ||
-+      ChildThread::current()->message_loop() == base::MessageLoop::current());
-+
-+  if (!make_context_current_.Run())
-+    return false;
-+
-+  gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
-+  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
-+
-+  return true;
-+}
-+
-+VaapiVideoDecodeAccelerator::TFPPicture*
-+    VaapiVideoDecodeAccelerator::TFPPictureById(int32 picture_buffer_id) {
-+  TFPPictures::iterator it = tfp_pictures_.find(picture_buffer_id);
-+  if (it == tfp_pictures_.end()) {
-+    DVLOG(1) << "Picture id " << picture_buffer_id << " does not exist";
-+    return NULL;
-+  }
-+
-+  return it->second.get();
-+}
-+
-+VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
-+    EGLDisplay egl_display, EGLContext egl_context,
-+    Client* client,
-+    const base::Callback<bool(void)>& make_context_current)
-+    : x_display_(0),
-+      egl_display_(egl_display),
-+      egl_context_(egl_context),
-+      make_context_current_(make_context_current),
-+      state_(kUninitialized),
-+      input_ready_(&lock_),
-+      surfaces_available_(&lock_),
-+      message_loop_(base::MessageLoop::current()),
-+      weak_this_(base::AsWeakPtr(this)),
-+      client_ptr_factory_(client),
-+      client_(client_ptr_factory_.GetWeakPtr()),
-+      decoder_thread_("VaapiDecoderThread"),
-+      num_frames_at_client_(0),
-+      num_stream_bufs_at_decoder_(0),
-+      finish_flush_pending_(false),
-+      awaiting_va_surfaces_recycle_(false),
-+      requested_num_pics_(0) {
-+  DCHECK(client);
-+}
-+VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+}
-+
-+class ScopedPtrXFree {
-+ public:
-+  void operator()(void* x) const {
-+    ::XFree(x);
-+  }
-+};
-+
-+bool VaapiVideoDecodeAccelerator::Initialize(
-+    media::VideoCodecProfile profile) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  base::AutoLock auto_lock(lock_);
-+  DCHECK_EQ(state_, kUninitialized);
-+  DVLOG(2) << "Initializing VAVDA, profile: " << profile;
-+
-+  if (!make_context_current_.Run())
-+    return false;
-+
-+  x_display_ = base::MessagePumpForUI::GetDefaultXDisplay();
-+
-+  vaapi_wrapper_ = VaapiWrapper::Create(
-+      profile, x_display_,
-+      base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR));
-+
-+  if (!vaapi_wrapper_.get()) {
-+    DVLOG(1) << "Failed initializing VAAPI";
-+    return false;
-+  }
-+
-+  decoder_.reset(
-+      new VaapiH264Decoder(
-+          vaapi_wrapper_.get(),
-+          media::BindToCurrentLoop(base::Bind(
-+              &VaapiVideoDecodeAccelerator::SurfaceReady, weak_this_)),
-+          base::Bind(&ReportToUMA)));
-+
-+  CHECK(decoder_thread_.Start());
-+
-+  state_ = kIdle;
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyInitializeDone, client_));
-+  return true;
-+}
-+
-+void VaapiVideoDecodeAccelerator::SurfaceReady(
-+    int32 input_id,
-+    const scoped_refptr<VASurface>& va_surface) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DCHECK(!awaiting_va_surfaces_recycle_);
-+
-+  // Drop any requests to output if we are resetting or being destroyed.
-+  if (state_ == kResetting || state_ == kDestroying)
-+    return;
-+
-+  pending_output_cbs_.push(
-+      base::Bind(&VaapiVideoDecodeAccelerator::OutputPicture,
-+                 weak_this_, va_surface, input_id));
-+
-+  TryOutputSurface();
-+}
-+
-+void VaapiVideoDecodeAccelerator::OutputPicture(
-+    const scoped_refptr<VASurface>& va_surface,
-+    int32 input_id,
-+    TFPPicture* tfp_picture) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  int32 output_id  = tfp_picture->picture_buffer_id();
-+
-+  TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface",
-+               "input_id", input_id,
-+               "output_id", output_id);
-+
-+  DVLOG(3) << "Outputting VASurface " << va_surface->id()
-+           << " into pixmap bound to picture buffer id " << output_id;
-+
-+  RETURN_AND_NOTIFY_ON_FAILURE(tfp_picture->Bind(),
-+                               "Failed binding texture to pixmap",
-+                               PLATFORM_FAILURE, );
-+
-+  RETURN_AND_NOTIFY_ON_FAILURE(
-+      vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface->id(),
-+                                           tfp_picture->x_pixmap(),
-+                                           tfp_picture->size()),
-+      "Failed putting surface into pixmap", PLATFORM_FAILURE, );
-+
-+  // Notify the client a picture is ready to be displayed.
-+  ++num_frames_at_client_;
-+  TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
-+  DVLOG(4) << "Notifying output picture id " << output_id
-+           << " for input "<< input_id << " is ready";
-+  client_->PictureReady(media::Picture(output_id, input_id));
-+}
-+
-+void VaapiVideoDecodeAccelerator::TryOutputSurface() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  // Handle Destroy() arriving while pictures are queued for output.
-+  if (!client_)
-+    return;
-+
-+  if (pending_output_cbs_.empty() || output_buffers_.empty())
-+    return;
-+
-+  OutputCB output_cb = pending_output_cbs_.front();
-+  pending_output_cbs_.pop();
-+
-+  TFPPicture* tfp_picture = TFPPictureById(output_buffers_.front());
-+  DCHECK(tfp_picture);
-+  output_buffers_.pop();
-+
-+  output_cb.Run(tfp_picture);
-+
-+  if (finish_flush_pending_ && pending_output_cbs_.empty())
-+    FinishFlush();
-+}
-+
-+void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
-+    const media::BitstreamBuffer& bitstream_buffer) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id",
-+      bitstream_buffer.id());
-+
-+  DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id()
-+           << " size: " << (int)bitstream_buffer.size();
-+
-+  scoped_ptr<base::SharedMemory> shm(
-+      new base::SharedMemory(bitstream_buffer.handle(), true));
-+  RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(bitstream_buffer.size()),
-+                              "Failed to map input buffer", UNREADABLE_INPUT,);
-+
-+  base::AutoLock auto_lock(lock_);
-+
-+  // Set up a new input buffer and queue it for later.
-+  linked_ptr<InputBuffer> input_buffer(new InputBuffer());
-+  input_buffer->shm.reset(shm.release());
-+  input_buffer->id = bitstream_buffer.id();
-+  input_buffer->size = bitstream_buffer.size();
-+
-+  ++num_stream_bufs_at_decoder_;
-+  TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
-+                 num_stream_bufs_at_decoder_);
-+
-+  input_buffers_.push(input_buffer);
-+  input_ready_.Signal();
-+}
-+
-+bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  lock_.AssertAcquired();
-+
-+  if (curr_input_buffer_.get())
-+    return true;
-+
-+  // Will only wait if it is expected that in current state new buffers will
-+  // be queued from the client via Decode(). The state can change during wait.
-+  while (input_buffers_.empty() && (state_ == kDecoding || state_ == kIdle)) {
-+    input_ready_.Wait();
-+  }
-+
-+  // We could have got woken up in a different state or never got to sleep
-+  // due to current state; check for that.
-+  switch (state_) {
-+    case kFlushing:
-+      // Here we are only interested in finishing up decoding buffers that are
-+      // already queued up. Otherwise will stop decoding.
-+      if (input_buffers_.empty())
-+        return false;
-+      // else fallthrough
-+    case kDecoding:
-+    case kIdle:
-+      DCHECK(!input_buffers_.empty());
-+
-+      curr_input_buffer_ = input_buffers_.front();
-+      input_buffers_.pop();
-+
-+      DVLOG(4) << "New current bitstream buffer, id: "
-+               << curr_input_buffer_->id
-+               << " size: " << curr_input_buffer_->size;
-+
-+      decoder_->SetStream(
-+          static_cast<uint8*>(curr_input_buffer_->shm->memory()),
-+          curr_input_buffer_->size, curr_input_buffer_->id);
-+      return true;
-+
-+    default:
-+      // We got woken up due to being destroyed/reset, ignore any already
-+      // queued inputs.
-+      return false;
-+  }
-+}
-+
-+void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
-+  lock_.AssertAcquired();
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  DCHECK(curr_input_buffer_.get());
-+
-+  int32 id = curr_input_buffer_->id;
-+  curr_input_buffer_.reset();
-+  DVLOG(4) << "End of input buffer " << id;
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyEndOfBitstreamBuffer, client_, id));
-+
-+  --num_stream_bufs_at_decoder_;
-+  TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
-+                 num_stream_bufs_at_decoder_);
-+}
-+
-+bool VaapiVideoDecodeAccelerator::FeedDecoderWithOutputSurfaces_Locked() {
-+  lock_.AssertAcquired();
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+
-+  while (available_va_surfaces_.empty() &&
-+         (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) {
-+    surfaces_available_.Wait();
-+  }
-+
-+  if (state_ != kDecoding && state_ != kFlushing && state_ != kIdle)
-+    return false;
-+
-+  VASurface::ReleaseCB va_surface_release_cb =
-+      media::BindToCurrentLoop(base::Bind(
-+          &VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_));
-+
-+  while (!available_va_surfaces_.empty()) {
-+    scoped_refptr<VASurface> va_surface(
-+        new VASurface(available_va_surfaces_.front(), va_surface_release_cb));
-+    available_va_surfaces_.pop_front();
-+    decoder_->ReuseSurface(va_surface);
-+  }
-+
-+  return true;
-+}
-+
-+void VaapiVideoDecodeAccelerator::DecodeTask() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask");
-+  base::AutoLock auto_lock(lock_);
-+
-+  if (state_ != kDecoding)
-+    return;
-+
-+  // Main decode task.
-+  DVLOG(4) << "Decode task";
-+
-+  // Try to decode what stream data is (still) in the decoder until we run out
-+  // of it.
-+  while (GetInputBuffer_Locked()) {
-+    DCHECK(curr_input_buffer_.get());
-+
-+    VaapiH264Decoder::DecResult res;
-+    {
-+      // We are OK releasing the lock here, as decoder never calls our methods
-+      // directly and we will reacquire the lock before looking at state again.
-+      // This is the main decode function of the decoder and while keeping
-+      // the lock for its duration would be fine, it would defeat the purpose
-+      // of having a separate decoder thread.
-+      base::AutoUnlock auto_unlock(lock_);
-+      res = decoder_->Decode();
-+    }
-+
-+    switch (res) {
-+      case VaapiH264Decoder::kAllocateNewSurfaces:
-+        DVLOG(1) << "Decoder requesting a new set of surfaces";
-+        message_loop_->PostTask(FROM_HERE, base::Bind(
-+            &VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, weak_this_,
-+                decoder_->GetRequiredNumOfPictures(),
-+                decoder_->GetPicSize()));
-+        // We'll get rescheduled once ProvidePictureBuffers() finishes.
-+        return;
-+
-+      case VaapiH264Decoder::kRanOutOfStreamData:
-+        ReturnCurrInputBuffer_Locked();
-+        break;
-+
-+      case VaapiH264Decoder::kRanOutOfSurfaces:
-+        // No more output buffers in the decoder, try getting more or go to
-+        // sleep waiting for them.
-+        if (!FeedDecoderWithOutputSurfaces_Locked())
-+          return;
-+
-+        break;
-+
-+      case VaapiH264Decoder::kDecodeError:
-+        RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream",
-+                                     PLATFORM_FAILURE, );
-+        return;
-+    }
-+  }
-+}
-+
-+void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(size_t num_pics,
-+                                                           gfx::Size size) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DCHECK(!awaiting_va_surfaces_recycle_);
-+
-+  // At this point decoder has stopped running and has already posted onto our
-+  // loop any remaining output request callbacks, which executed before we got
-+  // here. Some of them might have been pended though, because we might not
-+  // have had enough TFPictures to output surfaces to. Initiate a wait cycle,
-+  // which will wait for client to return enough PictureBuffers to us, so that
-+  // we can finish all pending output callbacks, releasing associated surfaces.
-+  DVLOG(1) << "Initiating surface set change";
-+  awaiting_va_surfaces_recycle_ = true;
-+
-+  requested_num_pics_ = num_pics;
-+  requested_pic_size_ = size;
-+
-+  TryFinishSurfaceSetChange();
-+}
-+
-+void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  if (!awaiting_va_surfaces_recycle_)
-+    return;
-+
-+  if (!pending_output_cbs_.empty() ||
-+      tfp_pictures_.size() != available_va_surfaces_.size()) {
-+    // Either:
-+    // 1. Not all pending pending output callbacks have been executed yet.
-+    // Wait for the client to return enough pictures and retry later.
-+    // 2. The above happened and all surface release callbacks have been posted
-+    // as the result, but not all have executed yet. Post ourselves after them
-+    // to let them release surfaces.
-+    DVLOG(2) << "Awaiting pending output/surface release callbacks to finish";
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, weak_this_));
-+    return;
-+  }
-+
-+  // All surfaces released, destroy them and dismiss all PictureBuffers.
-+  awaiting_va_surfaces_recycle_ = false;
-+  available_va_surfaces_.clear();
-+  vaapi_wrapper_->DestroySurfaces();
-+
-+  for (TFPPictures::iterator iter = tfp_pictures_.begin();
-+       iter != tfp_pictures_.end(); ++iter) {
-+    DVLOG(2) << "Dismissing picture id: " << iter->first;
-+    client_->DismissPictureBuffer(iter->first);
-+  }
-+  tfp_pictures_.clear();
-+
-+  // And ask for a new set as requested.
-+  DVLOG(1) << "Requesting " << requested_num_pics_ << " pictures of size: "
-+           << requested_pic_size_.ToString();
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::ProvidePictureBuffers, client_,
-+      requested_num_pics_, requested_pic_size_, GL_TEXTURE_2D));
-+}
-+
-+void VaapiVideoDecodeAccelerator::Decode(
-+    const media::BitstreamBuffer& bitstream_buffer) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id",
-+               bitstream_buffer.id());
-+
-+  // We got a new input buffer from the client, map it and queue for later use.
-+  MapAndQueueNewInputBuffer(bitstream_buffer);
-+
-+  base::AutoLock auto_lock(lock_);
-+  switch (state_) {
-+    case kIdle:
-+      state_ = kDecoding;
-+      decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+          &VaapiVideoDecodeAccelerator::DecodeTask,
-+          base::Unretained(this)));
-+      break;
-+
-+    case kDecoding:
-+      // Decoder already running.
-+    case kResetting:
-+      // When resetting, allow accumulating bitstream buffers, so that
-+      // the client can queue after-seek-buffers while we are finishing with
-+      // the before-seek one.
-+      break;
-+
-+    default:
-+      RETURN_AND_NOTIFY_ON_FAILURE(false,
-+          "Decode request from client in invalid state: " << state_,
-+          PLATFORM_FAILURE, );
-+      break;
-+  }
-+}
-+
-+void VaapiVideoDecodeAccelerator::RecycleVASurfaceID(
-+    VASurfaceID va_surface_id) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  base::AutoLock auto_lock(lock_);
-+
-+  available_va_surfaces_.push_back(va_surface_id);
-+  surfaces_available_.Signal();
-+}
-+
-+void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
-+    const std::vector<media::PictureBuffer>& buffers) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  base::AutoLock auto_lock(lock_);
-+  DCHECK(tfp_pictures_.empty());
-+
-+  while (!output_buffers_.empty())
-+    output_buffers_.pop();
-+
-+  RETURN_AND_NOTIFY_ON_FAILURE(
-+      buffers.size() == requested_num_pics_,
-+      "Got an invalid number of picture buffers. (Got " << buffers.size()
-+      << ", requested " << requested_num_pics_ << ")", INVALID_ARGUMENT, );
-+  DCHECK(requested_pic_size_ == buffers[0].size());
-+
-+  std::vector<VASurfaceID> va_surface_ids;
-+  RETURN_AND_NOTIFY_ON_FAILURE(
-+      vaapi_wrapper_->CreateSurfaces(requested_pic_size_,
-+                                     buffers.size(),
-+                                     &va_surface_ids),
-+      "Failed creating VA Surfaces", PLATFORM_FAILURE, );
-+  DCHECK_EQ(va_surface_ids.size(), buffers.size());
-+
-+  for (size_t i = 0; i < buffers.size(); ++i) {
-+    DVLOG(2) << "Assigning picture id: " << buffers[i].id()
-+             << " to texture id: " << buffers[i].texture_id()
-+             << " VASurfaceID: " << va_surface_ids[i];
-+
-+    linked_ptr<TFPPicture> tfp_picture(
-+        TFPPicture::Create(make_context_current_, egl_display_, x_display_,
-+                           buffers[i].id(), buffers[i].texture_id(),
-+                           requested_pic_size_));
-+
-+    RETURN_AND_NOTIFY_ON_FAILURE(
-+        tfp_picture.get(), "Failed assigning picture buffer to a texture.",
-+        PLATFORM_FAILURE, );
-+
-+    bool inserted = tfp_pictures_.insert(std::make_pair(
-+        buffers[i].id(), tfp_picture)).second;
-+    DCHECK(inserted);
-+
-+    output_buffers_.push(buffers[i].id());
-+    available_va_surfaces_.push_back(va_surface_ids[i]);
-+    surfaces_available_.Signal();
-+  }
-+
-+  state_ = kDecoding;
-+  decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::DecodeTask, base::Unretained(this)));
-+}
-+
-+void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id",
-+               picture_buffer_id);
-+
-+  --num_frames_at_client_;
-+  TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
-+
-+  output_buffers_.push(picture_buffer_id);
-+  TryOutputSurface();
-+}
-+
-+void VaapiVideoDecodeAccelerator::FlushTask() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  DVLOG(1) << "Flush task";
-+
-+  // First flush all the pictures that haven't been outputted, notifying the
-+  // client to output them.
-+  bool res = decoder_->Flush();
-+  RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.",
-+                               PLATFORM_FAILURE, );
-+
-+  // Put the decoder in idle state, ready to resume.
-+  decoder_->Reset();
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_));
-+}
-+
-+void VaapiVideoDecodeAccelerator::Flush() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DVLOG(1) << "Got flush request";
-+
-+  base::AutoLock auto_lock(lock_);
-+  state_ = kFlushing;
-+  // Queue a flush task after all existing decoding tasks to clean up.
-+  decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
-+
-+  input_ready_.Signal();
-+  surfaces_available_.Signal();
-+}
-+
-+void VaapiVideoDecodeAccelerator::FinishFlush() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  finish_flush_pending_ = false;
-+
-+  base::AutoLock auto_lock(lock_);
-+  if (state_ != kFlushing) {
-+    DCHECK_EQ(state_, kDestroying);
-+    return;  // We could've gotten destroyed already.
-+  }
-+
-+  // Still waiting for textures from client to finish outputting all pending
-+  // frames. Try again later.
-+  if (!pending_output_cbs_.empty()) {
-+    finish_flush_pending_ = true;
-+    return;
-+  }
-+
-+  state_ = kIdle;
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyFlushDone, client_));
-+
-+  DVLOG(1) << "Flush finished";
-+}
-+
-+void VaapiVideoDecodeAccelerator::ResetTask() {
-+  DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
-+  DVLOG(1) << "ResetTask";
-+
-+  // All the decoding tasks from before the reset request from client are done
-+  // by now, as this task was scheduled after them and client is expected not
-+  // to call Decode() after Reset() and before NotifyResetDone.
-+  decoder_->Reset();
-+
-+  base::AutoLock auto_lock(lock_);
-+
-+  // Return current input buffer, if present.
-+  if (curr_input_buffer_.get())
-+    ReturnCurrInputBuffer_Locked();
-+
-+  // And let client know that we are done with reset.
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
-+}
-+
-+void VaapiVideoDecodeAccelerator::Reset() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DVLOG(1) << "Got reset request";
-+
-+  // This will make any new decode tasks exit early.
-+  base::AutoLock auto_lock(lock_);
-+  state_ = kResetting;
-+  finish_flush_pending_ = false;
-+
-+  // Drop all remaining input buffers, if present.
-+  while (!input_buffers_.empty()) {
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &Client::NotifyEndOfBitstreamBuffer, client_,
-+        input_buffers_.front()->id));
-+    input_buffers_.pop();
-+  }
-+
-+  decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
-+
-+  input_ready_.Signal();
-+  surfaces_available_.Signal();
-+}
-+
-+void VaapiVideoDecodeAccelerator::FinishReset() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  DVLOG(1) << "FinishReset";
-+  base::AutoLock auto_lock(lock_);
-+
-+  if (state_ != kResetting) {
-+    DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_;
-+    return;  // We could've gotten destroyed already.
-+  }
-+
-+  // Drop pending outputs.
-+  while (!pending_output_cbs_.empty())
-+    pending_output_cbs_.pop();
-+
-+  if (awaiting_va_surfaces_recycle_) {
-+    // Decoder requested a new surface set while we were waiting for it to
-+    // finish the last DecodeTask, running at the time of Reset().
-+    // Let the surface set change finish first before resetting.
-+    message_loop_->PostTask(FROM_HERE, base::Bind(
-+        &VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
-+    return;
-+  }
-+
-+  num_stream_bufs_at_decoder_ = 0;
-+  state_ = kIdle;
-+
-+  message_loop_->PostTask(FROM_HERE, base::Bind(
-+      &Client::NotifyResetDone, client_));
-+
-+  // The client might have given us new buffers via Decode() while we were
-+  // resetting and might be waiting for our move, and not call Decode() anymore
-+  // until we return something. Post a DecodeTask() so that we won't
-+  // sleep forever waiting for Decode() in that case. Having two of them
-+  // in the pipe is harmless, the additional one will return as soon as it sees
-+  // that we are back in kDecoding state.
-+  if (!input_buffers_.empty()) {
-+    state_ = kDecoding;
-+    decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+      &VaapiVideoDecodeAccelerator::DecodeTask,
-+      base::Unretained(this)));
-+  }
-+
-+  DVLOG(1) << "Reset finished";
-+}
-+
-+void VaapiVideoDecodeAccelerator::Cleanup() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+
-+  if (state_ == kUninitialized || state_ == kDestroying)
-+    return;
-+
-+  DVLOG(1) << "Destroying VAVDA";
-+  base::AutoLock auto_lock(lock_);
-+  state_ = kDestroying;
-+
-+  client_ptr_factory_.InvalidateWeakPtrs();
-+
-+  {
-+    base::AutoUnlock auto_unlock(lock_);
-+    // Post a dummy task to the decoder_thread_ to ensure it is drained.
-+    base::WaitableEvent waiter(false, false);
-+    decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
-+        &base::WaitableEvent::Signal, base::Unretained(&waiter)));
-+    input_ready_.Signal();
-+    surfaces_available_.Signal();
-+    waiter.Wait();
-+    decoder_thread_.Stop();
-+  }
-+
-+  state_ = kUninitialized;
-+}
-+
-+void VaapiVideoDecodeAccelerator::Destroy() {
-+  DCHECK_EQ(message_loop_, base::MessageLoop::current());
-+  Cleanup();
-+  delete this;
-+}
-+
-+}  // namespace content
-diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h
-new file mode 100644
-index 0000000..d41cf38
---- /dev/null
-+++ b/content/common/gpu/media/vaapi_video_decode_accelerator_tizen.h
-@@ -0,0 +1,273 @@
-+// 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.
-+//
-+// This file contains an implementation of VideoDecoderAccelerator
-+// that utilizes hardware video decoder present on Intel CPUs for Tizen.
-+
-+#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
-+#define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
-+
-+#include <map>
-+#include <queue>
-+#include <utility>
-+#include <vector>
-+
-+#include "base/logging.h"
-+#include "base/memory/linked_ptr.h"
-+#include "base/memory/shared_memory.h"
-+#include "base/memory/weak_ptr.h"
-+#include "base/message_loop/message_loop.h"
-+#include "base/synchronization/condition_variable.h"
-+#include "base/synchronization/lock.h"
-+#include "base/threading/non_thread_safe.h"
-+#include "base/threading/thread.h"
-+#include "content/common/content_export.h"
-+#include "content/common/gpu/media/vaapi_h264_decoder.h"
-+#include "content/common/gpu/media/vaapi_wrapper.h"
-+#include "content/common/gpu/media/video_decode_accelerator_impl.h"
-+#include "media/base/bitstream_buffer.h"
-+#include "media/video/picture.h"
-+#include "media/video/video_decode_accelerator.h"
-+#include "ui/gl/gl_bindings.h"
-+
-+namespace content {
-+
-+// Class to provide video decode acceleration for Intel systems with hardware
-+// support for it, and on which libva is available.
-+// Decoding tasks are performed in a separate decoding thread.
-+//
-+// Threading/life-cycle: this object is created & destroyed on the GPU
-+// ChildThread.  A few methods on it are called on the decoder thread which is
-+// stopped during |this->Destroy()|, so any tasks posted to the decoder thread
-+// can assume |*this| is still alive.  See |weak_this_| below for more details.
-+class CONTENT_EXPORT VaapiVideoDecodeAccelerator
-+    : public VideoDecodeAcceleratorImpl {
-+ public:
-+  VaapiVideoDecodeAccelerator(
-+      EGLDisplay egl_display, EGLContext egl_context,
-+      Client* client,
-+      const base::Callback<bool(void)>& make_context_current);
-+  virtual ~VaapiVideoDecodeAccelerator();
-+
-+  // media::VideoDecodeAccelerator implementation.
-+  virtual bool Initialize(media::VideoCodecProfile profile) OVERRIDE;
-+  virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
-+  virtual void AssignPictureBuffers(
-+      const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
-+  virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
-+  virtual void Flush() OVERRIDE;
-+  virtual void Reset() OVERRIDE;
-+  virtual void Destroy() OVERRIDE;
-+
-+private:
-+  // Notify the client that |output_id| is ready for displaying.
-+  void NotifyPictureReady(int32 input_id, int32 output_id);
-+
-+  // Notify the client that an error has occurred and decoding cannot continue.
-+  void NotifyError(Error error);
-+
-+  // Map the received input buffer into this process' address space and
-+  // queue it for decode.
-+  void MapAndQueueNewInputBuffer(
-+      const media::BitstreamBuffer& bitstream_buffer);
-+
-+  // Get a new input buffer from the queue and set it up in decoder. This will
-+  // sleep if no input buffers are available. Return true if a new buffer has
-+  // been set up, false if an early exit has been requested (due to initiated
-+  // reset/flush/destroy).
-+  bool GetInputBuffer_Locked();
-+
-+  // Signal the client that the current buffer has been read and can be
-+  // returned. Will also release the mapping.
-+  void ReturnCurrInputBuffer_Locked();
-+
-+  // Pass one or more output buffers to the decoder. This will sleep
-+  // if no buffers are available. Return true if buffers have been set up or
-+  // false if an early exit has been requested (due to initiated
-+  // reset/flush/destroy).
-+  bool FeedDecoderWithOutputSurfaces_Locked();
-+
-+  // Continue decoding given input buffers and sleep waiting for input/output
-+  // as needed. Will exit if a new set of surfaces or reset/flush/destroy
-+  // is requested.
-+  void DecodeTask();
-+
-+  // Scheduled after receiving a flush request and executed after the current
-+  // decoding task finishes decoding pending inputs. Makes the decoder return
-+  // all remaining output pictures and puts it in an idle state, ready
-+  // to resume if needed and schedules a FinishFlush.
-+  void FlushTask();
-+
-+  // Scheduled by the FlushTask after decoder is flushed to put VAVDA into idle
-+  // state and notify the client that flushing has been finished.
-+  void FinishFlush();
-+
-+  // Scheduled after receiving a reset request and executed after the current
-+  // decoding task finishes decoding the current frame. Puts the decoder into
-+  // an idle state, ready to resume if needed, discarding decoded but not yet
-+  // outputted pictures (decoder keeps ownership of their associated picture
-+  // buffers). Schedules a FinishReset afterwards.
-+  void ResetTask();
-+
-+  // Scheduled by ResetTask after it's done putting VAVDA into an idle state.
-+  // Drops remaining input buffers and notifies the client that reset has been
-+  // finished.
-+  void FinishReset();
-+
-+  // Helper for Destroy(), doing all the actual work except for deleting self.
-+  void Cleanup();
-+
-+  // Get a usable framebuffer configuration for use in binding textures
-+  // or return false on failure.
-+  bool InitializeFBConfig();
-+
-+  // Callback for the decoder to execute when it wants us to output given
-+  // |va_surface|.
-+  void SurfaceReady(int32 input_id, const scoped_refptr<VASurface>& va_surface);
-+
-+  // Represents a texture bound to an X Pixmap for output purposes.
-+  class TFPPicture;
-+
-+  // Callback to be executed once we have a |va_surface| to be output and
-+  // an available |tfp_picture| to use for output.
-+  // Puts contents of |va_surface| into given |tfp_picture|, releases the
-+  // surface and passes the resulting picture to client for output.
-+  void OutputPicture(const scoped_refptr<VASurface>& va_surface,
-+                     int32 input_id,
-+                     TFPPicture* tfp_picture);
-+
-+  // Try to OutputPicture() if we have both a ready surface and picture.
-+  void TryOutputSurface();
-+
-+  // Called when a VASurface is no longer in use by the decoder or is not being
-+  // synced/waiting to be synced to a picture. Returns it to available surfaces
-+  // pool.
-+  void RecycleVASurfaceID(VASurfaceID va_surface_id);
-+
-+  // Initiate wait cycle for surfaces to be released before we release them
-+  // and allocate new ones, as requested by the decoder.
-+  void InitiateSurfaceSetChange(size_t num_pics, gfx::Size size);
-+  // Check if the surfaces have been released or post ourselves for later.
-+  void TryFinishSurfaceSetChange();
-+
-+  // Client-provided X/EGL state.
-+  Display* x_display_;
-+  EGLDisplay egl_display_;
-+  EGLContext egl_context_;
-+  base::Callback<bool(void)> make_context_current_;
-+
-+  // VAVDA state.
-+  enum State {
-+    // Initialize() not called yet or failed.
-+    kUninitialized,
-+    // DecodeTask running.
-+    kDecoding,
-+    // Resetting, waiting for decoder to finish current task and cleanup.
-+    kResetting,
-+    // Flushing, waiting for decoder to finish current task and cleanup.
-+    kFlushing,
-+    // Idle, decoder in state ready to start/resume decoding.
-+    kIdle,
-+    // Destroying, waiting for the decoder to finish current task.
-+    kDestroying,
-+  };
-+
-+  // Protects input buffer and surface queues and state_.
-+  base::Lock lock_;
-+  State state_;
-+
-+  // An input buffer awaiting consumption, provided by the client.
-+  struct InputBuffer {
-+    InputBuffer();
-+    ~InputBuffer();
-+
-+    int32 id;
-+    size_t size;
-+    scoped_ptr<base::SharedMemory> shm;
-+  };
-+
-+  // Queue for incoming input buffers.
-+  typedef std::queue<linked_ptr<InputBuffer> > InputBuffers;
-+  InputBuffers input_buffers_;
-+  // Signalled when input buffers are queued onto the input_buffers_ queue.
-+  base::ConditionVariable input_ready_;
-+
-+  // Current input buffer at decoder.
-+  linked_ptr<InputBuffer> curr_input_buffer_;
-+
-+  // Queue for incoming output buffers (texture ids).
-+  typedef std::queue<int32> OutputBuffers;
-+  OutputBuffers output_buffers_;
-+
-+  typedef std::map<int32, linked_ptr<TFPPicture> > TFPPictures;
-+  // All allocated TFPPictures, regardless of their current state. TFPPictures
-+  // are allocated once and destroyed at the end of decode.
-+  TFPPictures tfp_pictures_;
-+
-+  // Return a TFPPicture associated with given client-provided id.
-+  TFPPicture* TFPPictureById(int32 picture_buffer_id);
-+
-+  // VA Surfaces no longer in use that can be passed back to the decoder for
-+  // reuse, once it requests them.
-+  std::list<VASurfaceID> available_va_surfaces_;
-+  // Signalled when output surfaces are queued onto the available_va_surfaces_
-+  // queue.
-+  base::ConditionVariable surfaces_available_;
-+
-+  // Pending output requests from the decoder. When it indicates that we should
-+  // output a surface and we have an available TFPPicture (i.e. texture) ready
-+  // to use, we'll execute the callback passing the TFPPicture. The callback
-+  // will put the contents of the surface into the picture and return it to
-+  // the client, releasing the surface as well.
-+  // If we don't have any available TFPPictures at the time when the decoder
-+  // requests output, we'll store the request on pending_output_cbs_ queue for
-+  // later and run it once the client gives us more textures
-+  // via ReusePictureBuffer().
-+  typedef base::Callback<void(TFPPicture*)> OutputCB;
-+  std::queue<OutputCB> pending_output_cbs_;
-+
-+  // ChildThread's message loop
-+  base::MessageLoop* message_loop_;
-+
-+  // WeakPtr<> pointing to |this| for use in posting tasks from the decoder
-+  // thread back to the ChildThread.  Because the decoder thread is a member of
-+  // this class, any task running on the decoder thread is guaranteed that this
-+  // object is still alive.  As a result, tasks posted from ChildThread to
-+  // decoder thread should use base::Unretained(this), and tasks posted from the
-+  // decoder thread to the ChildThread should use |weak_this_|.
-+  base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_;
-+
-+  // To expose client callbacks from VideoDecodeAccelerator.
-+  // NOTE: all calls to these objects *MUST* be executed on message_loop_.
-+  base::WeakPtrFactory<Client> client_ptr_factory_;
-+  base::WeakPtr<Client> client_;
-+
-+  scoped_ptr<VaapiWrapper> vaapi_wrapper_;
-+
-+  // Comes after vaapi_wrapper_ to ensure its destructor is executed before
-+  // vaapi_wrapper_ is destroyed.
-+  scoped_ptr<VaapiH264Decoder> decoder_;
-+  base::Thread decoder_thread_;
-+
-+  int num_frames_at_client_;
-+  int num_stream_bufs_at_decoder_;
-+
-+  // Whether we are waiting for any pending_output_cbs_ to be run before
-+  // NotifyingFlushDone.
-+  bool finish_flush_pending_;
-+
-+  // Decoder requested a new surface set and we are waiting for all the surfaces
-+  // to be returned before we can free them.
-+  bool awaiting_va_surfaces_recycle_;
-+
-+  // Last requested number/resolution of output picture buffers.
-+  size_t requested_num_pics_;
-+  gfx::Size requested_pic_size_;
-+
-+  DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator);
-+};
-+
-+}  // namespace content
-+
-+#endif  // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
-diff --git a/content/content_common.gypi b/content/content_common.gypi
-index 9d6cb61..3f53dd5 100644
---- a/content/content_common.gypi
-+++ b/content/content_common.gypi
-@@ -583,6 +583,32 @@
-         '<(DEPTH)/third_party/libva',
-       ],
-     }],
-+    ['target_arch != "arm" and tizen_mobile == 1 and use_x11 == 1', {
-+      'dependencies': [
-+        '../media/media.gyp:media',
-+      ],
-+      'sources': [
-+        'common/gpu/media/h264_dpb.cc',
-+        'common/gpu/media/h264_dpb.h',
-+        'common/gpu/media/va_surface.h',
-+        'common/gpu/media/vaapi_h264_decoder.cc',
-+        'common/gpu/media/vaapi_h264_decoder.h',
-+        'common/gpu/media/vaapi_video_decode_accelerator_tizen.cc',
-+        'common/gpu/media/vaapi_video_decode_accelerator_tizen.h',
-+        'common/gpu/media/vaapi_wrapper.cc',
-+        'common/gpu/media/vaapi_wrapper.h',
-+      ],
-+      'include_dirs': [
-+        '<(DEPTH)/third_party/libva',
-+        '<(DEPTH)/third_party/khronos',
-+      ],
-+      'link_settings': {
-+        'libraries': [
-+          '-lEGL',
-+          '-lGLESv2',
-+        ],
-+      },
-+    }],
-     ['OS=="win"', {
-       'dependencies': [
-         '../media/media.gyp:media',
-diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
-index 9e29e03..2c04d40 100644
---- a/content/gpu/gpu_main.cc
-+++ b/content/gpu/gpu_main.cc
-@@ -42,7 +42,8 @@
- #include "sandbox/win/src/sandbox.h"
- #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
- #include "content/common/gpu/media/exynos_video_decode_accelerator.h"
--#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
-+#elif (defined(OS_CHROMEOS) || defined(OS_TIZEN_MOBILE)) &&\
-+ defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
- #include "content/common/gpu/media/vaapi_wrapper.h"
- #endif
-@@ -360,7 +361,8 @@ bool WarmUpSandbox(const CommandLine& command_line) {
- #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
-   ExynosVideoDecodeAccelerator::PreSandboxInitialization();
--#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
-+#elif (defined(OS_CHROMEOS) || defined(OS_TIZEN_MOBILE)) &&\
-+ defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
-   VaapiWrapper::PreSandboxInitialization();
- #endif
--- 
-1.8.3.2
-
index 3e2ed89..5a327fd 100644 (file)
@@ -2,7 +2,7 @@
 %bcond_with wayland
 
 Name:           crosswalk
-Version:        5.34.105.0
+Version:        6.34.113.0
 Release:        0
 Summary:        Crosswalk is an app runtime based on Chromium
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -16,7 +16,6 @@ Source1001:     crosswalk.manifest
 Source1002:     %{name}.xml.in
 Source1003:     %{name}.png
 Patch1:         %{name}-do-not-look-for-gtk2-when-using-aura.patch
-Patch7:         %{name}-tizen-audio-session-manager.patch
 Patch8:         %{name}-mesa-ozone-typedefs.patch
 Patch9:         Blink-Add-GCC-flag-Wno-narrowing-fix-64bits-build.patch
 
@@ -26,13 +25,13 @@ BuildRequires:  expat-devel
 BuildRequires:  flex
 BuildRequires:  gperf
 BuildRequires:  libcap-devel
+BuildRequires:  ninja
 BuildRequires:  python
 BuildRequires:  python-xml
 BuildRequires:  perl
 BuildRequires:  which
 BuildRequires:  pkgconfig(alsa)
 BuildRequires:  pkgconfig(appcore-common)
-BuildRequires:  pkgconfig(audio-session-mgr)
 BuildRequires:  pkgconfig(cairo)
 BuildRequires:  pkgconfig(capi-location-manager)
 BuildRequires:  pkgconfig(dbus-1)
@@ -107,7 +106,6 @@ cp -a src/LICENSE LICENSE.chromium
 cp -a src/xwalk/LICENSE LICENSE.xwalk
 
 %patch1
-%patch7
 
 %if "%{tizen}" < "3.0"
 %patch2
@@ -143,34 +141,20 @@ export LDFLAGS="${LDFLAGS} -Wl,--no-keep-memory"
 # build root to the BUILDDIR_NAME definition, such as "/var/tmp/xwalk-build"
 # (remember all paths are still inside the chroot):
 #    gbs build --define 'BUILDDIR_NAME /some/path'
-#
-# The --depth and --generator-output combo is used to put all the Makefiles
-# inside the build directory, and (this is the important part) keep file lists
-# (generatedwith <|() in gyp) in the build directory as well, otherwise they
-# will be in the source directory, erased every time and trigger an almost full
-# Blink rebuild (among other smaller targets).
-# We cannot always pass those flags, though, because gyp's make generator does
-# not work if the --generator-output is the top-level source directory.
 BUILDDIR_NAME="%{?BUILDDIR_NAME}"
-if [ -z "${BUILDDIR_NAME}" ]; then
-   BUILDDIR_NAME="."
-else
-   GYP_EXTRA_FLAGS="--depth=. --generator-output=${BUILDDIR_NAME}"
+if [ -n "${BUILDDIR_NAME}" ]; then
+   mkdir -p "${BUILDDIR_NAME}"
+   ln -s "${BUILDDIR_NAME}" src/out
 fi
 
 %if %{with wayland}
-GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ash=1 -Duse_ozone=1"
+GYP_EXTRA_FLAGS="${GYP_EXTRA_FLAGS} -Duse_ozone=1"
 %endif
 
-# Change src/ so that we can pass "." to --depth below, otherwise we would need
-# to pass "src" to it, but this confuses the gyp make generator, that expects
-# to be called from the root source directory.
-cd src
-
 # --no-parallel is added because chroot does not mount a /dev/shm, this will
 # cause python multiprocessing.SemLock error.
-export GYP_GENERATORS='make'
-./xwalk/gyp_xwalk xwalk/xwalk.gyp \
+export GYP_GENERATORS='ninja'
+./src/xwalk/gyp_xwalk src/xwalk/xwalk.gyp \
 --no-parallel \
 ${GYP_EXTRA_FLAGS} \
 -Dchromeos=0 \
@@ -182,55 +166,32 @@ ${GYP_EXTRA_FLAGS} \
 -Duse_gconf=0 \
 -Duse_kerberos=0 \
 -Duse_system_bzip2=1 \
--Duse_system_icu=1 \
 -Duse_system_libexif=1 \
 -Duse_system_libxml=1 \
 -Duse_system_nspr=1 \
--Denable_xi21_mt=1 \
--Duse_xi2_mt=0 \
 -Denable_hidpi=1
 
-make %{?_smp_mflags} -C "${BUILDDIR_NAME}" BUILDTYPE=Release xwalk xwalkctl xwalk_launcher xwalk-pkg-helper
+ninja %{?_smp_mflags} -C src/out/Release xwalk xwalkctl xwalk_launcher xwalk-pkg-helper
 
 %install
-# Support building in a non-standard directory, possibly outside %{_builddir}.
-# Since the build root is erased every time a new build is performed, one way
-# to avoid losing the build directory is to specify a location outside the
-# build root to the BUILDDIR_NAME definition, such as "/var/tmp/xwalk-build"
-# (remember all paths are still inside the chroot):
-#    gbs build --define 'BUILDDIR_NAME /some/path'
-BUILDDIR_NAME="%{?BUILDDIR_NAME}"
-if [ -z "${BUILDDIR_NAME}" ]; then
-   BUILDDIR_NAME="."
-fi
-
-# Since BUILDDIR_NAME can be either a relative path or an absolute one, we need
-# to cd into src/ so that it means the same thing in the build and install
-# stages: during the former, a relative location refers to a place inside src/,
-# whereas during the latter a relative location by default would refer to a
-# place one directory above src/. If BUILDDIR_NAME is an absolute path, this is
-# irrelevant anyway.
-cd src
-
 # Binaries.
-install -p -D ../xwalk %{buildroot}%{_bindir}/xwalk
+install -p -D xwalk %{buildroot}%{_bindir}/xwalk
 install -p -D %{SOURCE2} %{buildroot}%{_dbusservicedir}/org.crosswalkproject.Runtime1.service
-install -p -D ../xwalk.service %{buildroot}%{_systemduserservicedir}/xwalk.service
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalk %{buildroot}%{_libdir}/xwalk/xwalk
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalkctl %{buildroot}%{_bindir}/xwalkctl
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalk-launcher %{buildroot}%{_bindir}/xwalk-launcher
+install -p -D xwalk.service %{buildroot}%{_systemduserservicedir}/xwalk.service
+install -p -D src/out/Release/xwalk %{buildroot}%{_libdir}/xwalk/xwalk
+install -p -D src/out/Release/xwalkctl %{buildroot}%{_bindir}/xwalkctl
+install -p -D src/out/Release/xwalk-launcher %{buildroot}%{_bindir}/xwalk-launcher
 # xwalk-pkg-helper needs to be set-user-ID-root so it can finish the installation process.
-install -m 06755 -p -D ${BUILDDIR_NAME}/out/Release/xwalk-pkg-helper %{buildroot}%{_bindir}/xwalk-pkg-helper
+install -m 06755 -p -D src/out/Release/xwalk-pkg-helper %{buildroot}%{_bindir}/xwalk-pkg-helper
 
 # Supporting libraries and resources.
-install -p -D ${BUILDDIR_NAME}/out/Release/icudtl.dat %{buildroot}%{_libdir}/xwalk/icudtl.dat
-install -p -D ${BUILDDIR_NAME}/out/Release/libffmpegsumo.so %{buildroot}%{_libdir}/xwalk/libffmpegsumo.so
-install -p -D ${BUILDDIR_NAME}/out/Release/xwalk.pak %{buildroot}%{_libdir}/xwalk/xwalk.pak
+install -p -D src/out/Release/icudtl.dat %{buildroot}%{_libdir}/xwalk/icudtl.dat
+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
 
 # Register xwalk to the package manager.
-install -p -D ../%{name}.xml %{buildroot}%{_manifestdir}/%{name}.xml
-install -p -D ../%{name}.png %{buildroot}%{_desktop_icondir}/%{name}.png
-
+install -p -D %{name}.xml %{buildroot}%{_manifestdir}/%{name}.xml
+install -p -D %{name}.png %{buildroot}%{_desktop_icondir}/%{name}.png
 
 %post
 mkdir -p %{_desktop_icondir_ro}
diff --git a/src/xwalk/runtime/android/core/src/org/xwalk/core/SslErrorHandler.java b/src/xwalk/runtime/android/core/src/org/xwalk/core/SslErrorHandler.java
deleted file mode 100644 (file)
index ccf12a7..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.xwalk.core;
-
-import android.os.Handler;
-
-/**
- * SslErrorHandler: class responsible for handling SSL errors.
- * This class is passed as a parameter to BrowserCallback.displaySslErrorDialog
- * and is meant to receive the user's response.
- */
-public class SslErrorHandler extends Handler {
-
-    /**
-     * @hide Only for use by WebViewProvider implementations.
-     */
-    public SslErrorHandler() {}
-
-    /**
-     * Proceed with the SSL certificate.
-     */
-    public void proceed() {}
-
-    /**
-     * Cancel this request and all pending requests for the XWalkView that had
-     * the error.
-     */
-    public void cancel() {}
-}
diff --git a/src/xwalk/runtime/android/core/src/org/xwalk/core/SslUtil.java b/src/xwalk/runtime/android/core/src/org/xwalk/core/SslUtil.java
new file mode 100644 (file)
index 0000000..430daf7
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core;
+
+import android.net.http.SslCertificate;
+import android.net.http.SslError;
+import android.util.Log;
+
+import org.chromium.net.NetError;
+import org.chromium.net.X509Util;
+
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+class SslUtil {
+    private static final String TAG = "SslUtil";
+
+    /**
+     * Creates an SslError object from a chromium net error code.
+     */
+    public static SslError sslErrorFromNetErrorCode(int error, SslCertificate cert, String url) {
+        assert (error >= NetError.ERR_CERT_END && error <= NetError.ERR_CERT_COMMON_NAME_INVALID);
+        switch(error) {
+            case NetError.ERR_CERT_COMMON_NAME_INVALID:
+                return new SslError(SslError.SSL_IDMISMATCH, cert, url);
+            case NetError.ERR_CERT_DATE_INVALID:
+                return new SslError(SslError.SSL_DATE_INVALID, cert, url);
+            case NetError.ERR_CERT_AUTHORITY_INVALID:
+                return new SslError(SslError.SSL_UNTRUSTED, cert, url);
+            default:
+                break;
+        }
+        // Map all other codes to SSL_INVALID.
+        return new SslError(SslError.SSL_INVALID, cert, url);
+    }
+
+    public static SslCertificate getCertificateFromDerBytes(byte[] derBytes) {
+        if (derBytes == null) {
+            return null;
+        }
+
+        try {
+            X509Certificate x509Certificate =
+                    X509Util.createCertificateFromBytes(derBytes);
+            return new SslCertificate(x509Certificate);
+        } catch (CertificateException e) {
+            // A SSL related exception must have occured.  This shouldn't happen.
+            Log.w(TAG, "Could not read certificate: " + e);
+        } catch (KeyStoreException e) {
+            // A SSL related exception must have occured.  This shouldn't happen.
+            Log.w(TAG, "Could not read certificate: " + e);
+        } catch (NoSuchAlgorithmException e) {
+            // A SSL related exception must have occured.  This shouldn't happen.
+            Log.w(TAG, "Could not read certificate: " + e);
+        }
+        return null;
+    }
+}
index c27fa1d..74f7145 100644 (file)
@@ -20,6 +20,7 @@ import android.graphics.Bitmap;
 import android.net.http.SslError;
 import android.os.Message;
 import android.view.KeyEvent;
+import android.webkit.ValueCallback;
 import android.webkit.WebResourceResponse;
 
 public class XWalkClient {
@@ -185,13 +186,14 @@ public class XWalkClient {
      * load.
      *
      * @param view The XWalkView that is initiating the callback.
-     * @param handler An SslErrorHandler object that will handle the user's
-     *            response.
+     * @param callback The callback class. Passing 'true' means accepting the
+     *                 ssl error and continue to load. Passing 'false' means
+     *                 forbidding to load the web page.
      * @param error The SSL error object.
      */
-    public void onReceivedSslError(XWalkView view, SslErrorHandler handler,
+    public void onReceivedSslError(XWalkView view, ValueCallback<Boolean> callback,
             SslError error) {
-        handler.cancel();
+        callback.onReceiveValue(true);
     }
 
     /**
index b4fe314..18cb146 100644 (file)
@@ -356,6 +356,11 @@ public class XWalkContent extends FrameLayout {
         loadUrl(url);
     }
 
+    @CalledByNative
+    public void onGetFullscreenFlagFromManifest(boolean enterFullscreen) {
+        if (enterFullscreen) getXWalkWebChromeClient().onToggleFullscreen(true);
+    }
+
     public void destroy() {
         if (mXWalkContent == 0) return;
 
index a52d61f..bd18870 100644 (file)
@@ -126,7 +126,7 @@ public abstract class XWalkContentsClient extends ContentViewClient {
     public abstract void onReceivedHttpAuthRequest(XWalkHttpAuthHandler handler,
             String host, String realm);
 
-    public abstract void onReceivedSslError(SslErrorHandler handler, SslError error);
+    public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error);
 
     public abstract void onReceivedLoginRequest(String realm, String account, String args);
 
index 3b5ee39..98f4dc7 100644 (file)
@@ -157,10 +157,12 @@ class XWalkContentsClientBridge extends XWalkContentsClient
         if (mXWalkClient != null && mXWalkView != null)
             mXWalkClient.onReceivedHttpAuthRequest(mXWalkView, handler, host, realm);
     }
+
     @Override
-    public void onReceivedSslError(SslErrorHandler handler, SslError error) {
-        if (mXWalkClient != null && mXWalkView != null)
-            mXWalkClient.onReceivedSslError(mXWalkView, handler, error);
+    public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) {
+        if (mXWalkClient != null && mXWalkView != null) {
+            mXWalkClient.onReceivedSslError(mXWalkView, callback, error);
+        }
     }
 
     @Override
@@ -375,8 +377,20 @@ class XWalkContentsClientBridge extends XWalkContentsClient
     @CalledByNative
     private boolean allowCertificateError(int certError, byte[] derBytes, final String url,
             final int id) {
-        // TODO(yongsheng): Implement this.
-        return false;
+        final SslCertificate cert = SslUtil.getCertificateFromDerBytes(derBytes);
+        if (cert == null) {
+            // if the certificate or the client is null, cancel the request
+            return false;
+        }
+        final SslError sslError = SslUtil.sslErrorFromNetErrorCode(certError, cert, url);
+        ValueCallback<Boolean> callback = new ValueCallback<Boolean>() {
+            @Override
+            public void onReceiveValue(Boolean value) {
+                proceedSslError(value.booleanValue(), id);
+            }
+        };
+        onReceivedSslError(callback, sslError);
+        return true;
     }
 
     private void proceedSslError(boolean proceed, int id) {
index fbdf296..0257f80 100644 (file)
@@ -14,18 +14,12 @@ import android.os.Message;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.webkit.ValueCallback;
 import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import org.xwalk.core.HttpAuthDatabase;
-import org.xwalk.core.XWalkHttpAuthHandler;
-import org.xwalk.core.R;
-import org.xwalk.core.SslErrorHandler;
-import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkView;
-
 // TODO(yongsheng): remove public modifier.
 public class XWalkDefaultClient extends XWalkClient {
 
@@ -78,23 +72,22 @@ public class XWalkDefaultClient extends XWalkClient {
     }
 
     @Override
-    public void onReceivedSslError(XWalkView view, SslErrorHandler handler,
+    public void onReceivedSslError(XWalkView view, ValueCallback<Boolean> callback,
             SslError error) {
-        final SslErrorHandler sslHandler = handler;
+        final ValueCallback<Boolean> valueCallback = callback;
         AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+        // Don't use setOnDismissListener because it's supported since API level 17.
         dialogBuilder.setTitle(R.string.ssl_alert_title)
                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
-                        sslHandler.proceed();
+                        valueCallback.onReceiveValue(true);
                         dialog.dismiss();
                     }
-                })
-                .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        sslHandler.cancel();
-                        dialog.cancel();
+                }).setNegativeButton(android.R.string.cancel, null)
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        valueCallback.onReceiveValue(false);
                     }
                 });
         mDialog = dialogBuilder.create();
index bb17ec2..7301141 100644 (file)
@@ -6,6 +6,8 @@ package org.xwalk.core.extension.api.contacts;
 
 import android.content.ContentResolver;
 import android.database.Cursor;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Event;
@@ -261,10 +263,11 @@ public class ContactFinder {
                 long id = c.getLong(c.getColumnIndex(Data.CONTACT_ID));
                 if (!dataMap.containsKey(id)) dataMap.put(id, new ContactData());
                 ContactData d = dataMap.get(id);
+                if (d.lastUpdated == null && VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
+                    d.lastUpdated = mUtils.getLastUpdated(id);
+                }
                 String mime = c.getString(c.getColumnIndex(Data.MIMETYPE));
-                if (mime.equals(ContactConstants.CUSTOM_MIMETYPE_LASTUPDATED)) {
-                    d.lastUpdated = c.getString(c.getColumnIndex(Data.DATA1));
-                } else if (mime.equals(StructuredName.CONTENT_ITEM_TYPE)) {
+                if (mime.equals(StructuredName.CONTENT_ITEM_TYPE)) {
                     d.oName = addString(d.oName, c, "displayName", StructuredName.DISPLAY_NAME);
                     d.oName = addArrayTop(d.oName, c, "honorificPrefixes", StructuredName.PREFIX);
                     d.oName = addArrayTop(d.oName, c, "givenNames", StructuredName.GIVEN_NAME);
index 133fb1e..074686e 100644 (file)
@@ -170,10 +170,6 @@ public class ContactSaver {
         }
     }
 
-    private void buildByDate(String name, String mimeType, String data) {
-        buildByDate(name, mimeType, data, null, 0);
-    }
-
     private void buildByDate(String name, String mimeType, String data, String type, int dateType) {
         if (!mContact.has(name)) return;
 
@@ -200,12 +196,12 @@ public class ContactSaver {
         }
     }
 
-    private void PutToContact(String id) {
-        if (id == null) return;
+    private void PutToContact(String name, String value) {
+        if (name == null) return;
         try {
-            mContact.put("id", id);
+            mContact.put(name, value);
         } catch (JSONException e) {
-            Log.e(TAG, "Failed to put id " + id + " into contact" + e.toString());
+            Log.e(TAG, "Failed to set " + name + " = " + value + " for contact" + e.toString());
         }
     }
 
@@ -281,7 +277,6 @@ public class ContactSaver {
             }
         }
 
-        buildByDate("lastUpdated", ContactConstants.CUSTOM_MIMETYPE_LASTUPDATED, Data.DATA1);
         buildByEvent("birthday", Event.TYPE_BIRTHDAY);
         buildByEvent("anniversary", Event.TYPE_ANNIVERSARY);
 
@@ -311,8 +306,11 @@ public class ContactSaver {
                         + "new raw ids are: " + newRawIds.toString());
                 return mContact;
             }
-            String id = mUtils.getId(newRawIds.iterator().next());
-            PutToContact(id);
+            mId = mUtils.getId(newRawIds.iterator().next());
+            PutToContact("id", mId);
+        }
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2 ) {
+            PutToContact("lastUpdated", String.valueOf(mUtils.getLastUpdated(Long.valueOf(mId))));
         }
         return mContact;
     }
index a850f4b..9ad8b27 100644 (file)
@@ -108,6 +108,29 @@ public class ContactUtils {
         }
     }
 
+    /**
+     * Get lastUpdatedTimestamp and return as JS date format
+     * @param long e.g. 987654321012
+     * @return string e.g. "2001-04-19T04:25:21.012Z"
+     */
+    @android.annotation.TargetApi(android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
+    public String getLastUpdated(long contactId) {
+        String[] projection = new String[]{ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP};
+
+        Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
+        Cursor cursor = mResolver.query(uri, projection, null, null, null);
+        try {
+            if (cursor.moveToNext()) {
+                return timeConvertToJS(cursor.getLong(0));
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
     public Set<String> getCurrentRawIds() {
         Cursor c = null;
         try {
@@ -277,4 +300,15 @@ public class ContactUtils {
         }
         return date;
     }
+
+    /**
+     * Convert epoch seconds to JS date format
+     * @param long e.g. 61
+     * @return string e.g. "1969-12-31T00:01:01Z"
+     */
+    private String timeConvertToJS(long seconds) {
+        final SimpleDateFormat df =
+                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", java.util.Locale.getDefault());
+        return df.format(new java.util.Date(seconds));
+    }
 }
index baad915..525e03f 100644 (file)
@@ -175,7 +175,7 @@ window.ContactName = function(init) {
 
 window.Contact = function(init) {
   this.id = null;
-  this.lastUpdated = null;
+  this.lastUpdated = new Date();
   this.name = init.name;
   this.emails = init.emails;
   this.photos = init.photos;
index 1a478ef..aa01c41 100644 (file)
@@ -27,7 +27,7 @@
         Finished to download file.
       </message>
       <message desc="Title for the Ssl Alert dialog [CHAR-LIMIT=32]" name="IDS_SSL_ALERT_TITLE">
-        Ssl Alert
+        Ssl Certificate Error Alert
       </message>
       <message desc="Title for the http authentication dialog [CHAR-LIMIT=32]" name="IDS_HTTP_AUTH_TITLE">
         Authentication Required
index 0fb96f5..a2de6ee 100644 (file)
@@ -7,11 +7,11 @@ package org.xwalk.runtime;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.net.http.SslError;
+import android.webkit.ValueCallback;
 
 import java.lang.reflect.Method;
 
 import org.xwalk.core.XWalkDefaultClient;
-import org.xwalk.core.SslErrorHandler;
 import org.xwalk.core.XWalkView;
 
 class XWalkClientForTest extends XWalkDefaultClient {
@@ -37,14 +37,14 @@ class XWalkClientForTest extends XWalkDefaultClient {
     }
 
     @Override
-    public void onReceivedSslError(XWalkView view, SslErrorHandler handler,
+    public void onReceivedSslError(XWalkView view, ValueCallback<Boolean> callback,
             SslError error) {
         if (mCallbackForTest != null) {
             try {
                 Class<?> objectClass = mCallbackForTest.getClass();
                 Method onReceivedSslError = objectClass.getMethod(
-                        "onReceivedSslError", SslErrorHandler.class, SslError.class);
-                onReceivedSslError.invoke(mCallbackForTest, handler, error);
+                        "onReceivedSslError", ValueCallback.class, SslError.class);
+                onReceivedSslError.invoke(mCallbackForTest, callback, error);
             } catch (Exception e) {
                 e.printStackTrace();
             }
index 9e36cb1..7fa476e 100644 (file)
@@ -54,15 +54,6 @@ int XWalkMainDelegateAndroid::RunProcess(
 }
 
 void XWalkMainDelegateAndroid::InitResourceBundle() {
-  int pak_fd =
-      base::GlobalDescriptors::GetInstance()->MaybeGet(kXWalkPakDescriptor);
-  if (pak_fd != base::kInvalidPlatformFileValue) {
-    ui::ResourceBundle::InitSharedInstanceWithPakFile(
-        base::File(pak_fd), false);
-    ResourceBundle::GetSharedInstance().AddDataPackFromFile(
-        base::File(pak_fd), ui::SCALE_FACTOR_100P);
-    return;
-  }
   base::FilePath pak_file;
   base::FilePath pak_dir;
   bool got_path = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_dir);
index 3de726c..96a1ab2 100644 (file)
@@ -99,11 +99,8 @@ void XWalkRenderViewHostExt::DidNavigateAnyFrame(
     const content::FrameNavigateParams& params) {
   DCHECK(CalledOnValidThread());
 
-  // TODO(Xingnan): Add the AddVisitedURLs method
-  // in RuntimeContext.
-
-  // RuntimeContext::FromWebContents(web_contents())
-  //    ->AddVisitedURLs(params.redirects);
+  RuntimeContext::FromWebContents(web_contents())
+      ->AddVisitedURLs(params.redirects);
 }
 
 bool XWalkRenderViewHostExt::OnMessageReceived(const IPC::Message& message) {
index d62009e..a4893f7 100644 (file)
@@ -44,6 +44,7 @@ using base::android::ScopedJavaLocalRef;
 using content::BrowserThread;
 using content::WebContents;
 using navigation_interception::InterceptNavigationDelegate;
+using xwalk::application_manifest_keys::kDisplay;
 
 namespace xwalk {
 
@@ -216,13 +217,9 @@ jboolean XWalkContent::SetManifest(JNIEnv* env,
     // According to original proposal for "app:launch:local_path", the "http"
     // and "https" schemes are supported. So |url| should do nothing when it
     // already has "http" or "https" scheme.
-    std::string lower_url = url;
-    std::transform(lower_url.begin(), lower_url.end(),
-                   lower_url.begin(), std::tolower);
-    if (lower_url.find(content::kHttpScheme) == std::string::npos &&
-        lower_url.find(content::kHttpsScheme) == std::string::npos) {
+    std::string scheme = GURL(url).scheme();
+    if (scheme != content::kHttpScheme && scheme != content::kHttpsScheme)
       url = path_str + url;
-    }
   } else {
     manifest.GetString(
         xwalk::application_manifest_keys::kLaunchWebURLKey, &url);
@@ -239,6 +236,17 @@ jboolean XWalkContent::SetManifest(JNIEnv* env,
   ScopedJavaLocalRef<jstring> url_buffer =
       base::android::ConvertUTF8ToJavaString(env, url);
 
+  if (manifest.HasPath(kDisplay)) {
+    std::string display_string;
+    manifest.GetString(kDisplay, &display_string);
+    // TODO(David): update the handling process of the display strings
+    // including fullscreen etc.
+    bool display_as_fullscreen = (
+        display_string.find("fullscreen") != std::string::npos);
+    Java_XWalkContent_onGetFullscreenFlagFromManifest(
+        env, obj, display_as_fullscreen ? JNI_TRUE : JNI_FALSE);
+  }
+
   // Check whether need to display launch screen. (Read from manifest.json)
   if (manifest.HasPath(
           xwalk::application_manifest_keys::kLaunchScreen)) {
index ac7bfe4..b0779d6 100644 (file)
@@ -40,7 +40,7 @@ void RunUpdateNotificationIconOnUIThread(
     int route_id,
     const SkBitmap& icon) {
   XWalkContentsClientBridgeBase* bridge =
-      XWalkContentsClientBridgeBase::FromID(process_id, route_id);
+      XWalkContentsClientBridgeBase::FromRenderViewID(process_id, route_id);
   if (bridge)
     bridge->UpdateNotificationIcon(notification_id, icon);
 }
index 89a8d24..4481431 100644 (file)
@@ -6,6 +6,7 @@
 #include "xwalk/runtime/browser/android/xwalk_contents_client_bridge_base.h"
 
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 
@@ -55,7 +56,7 @@ XWalkContentsClientBridgeBase* XWalkContentsClientBridgeBase::FromWebContents(
 }
 
 // static
-XWalkContentsClientBridgeBase* XWalkContentsClientBridgeBase::FromID(
+XWalkContentsClientBridgeBase* XWalkContentsClientBridgeBase::FromRenderViewID(
     int render_process_id,
     int render_view_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -67,6 +68,19 @@ XWalkContentsClientBridgeBase* XWalkContentsClientBridgeBase::FromID(
   return UserData::GetContents(web_contents);
 }
 
+// static
+XWalkContentsClientBridgeBase* XWalkContentsClientBridgeBase::FromRenderFrameID(
+    int render_process_id,
+    int render_frame_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  content::RenderFrameHost* rfh =
+      content::RenderFrameHost::FromID(render_process_id, render_frame_id);
+  if (!rfh) return NULL;
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(rfh);
+  return UserData::GetContents(web_contents);
+}
+
 XWalkContentsClientBridgeBase::~XWalkContentsClientBridgeBase() {
 }
 
index 555e890..a967548 100644 (file)
@@ -35,8 +35,10 @@ class XWalkContentsClientBridgeBase {
                         XWalkContentsClientBridgeBase* handler);
   static XWalkContentsClientBridgeBase* FromWebContents(
       content::WebContents* web_contents);
-  static XWalkContentsClientBridgeBase* FromID(int render_process_id,
+  static XWalkContentsClientBridgeBase* FromRenderViewID(int render_process_id,
                                             int render_view_id);
+  static XWalkContentsClientBridgeBase* FromRenderFrameID(int render_process_id,
+                                            int render_frame_id);
 
   virtual ~XWalkContentsClientBridgeBase();
 
index 2eef174..140c46b 100644 (file)
@@ -57,7 +57,7 @@ bool XWalkCookieAccessPolicy::AllowGetCookie(
     const net::CookieList& cookie_list,
     content::ResourceContext* context,
     int render_process_id,
-    int render_view_id) {
+    int render_frame_id) {
   return GetGlobalAllowAccess();
 }
 
@@ -67,7 +67,7 @@ bool XWalkCookieAccessPolicy::AllowSetCookie(
     const std::string& cookie_line,
     content::ResourceContext* context,
     int render_process_id,
-    int render_view_id,
+    int render_frame_id,
     net::CookieOptions* options) {
   return GetGlobalAllowAccess();
 }
index 7104d4b..2574328 100644 (file)
@@ -50,13 +50,13 @@ class XWalkCookieAccessPolicy {
                       const net::CookieList& cookie_list,
                       content::ResourceContext* context,
                       int render_process_id,
-                      int render_view_id);
+                      int render_frame_id);
   bool AllowSetCookie(const GURL& url,
                       const GURL& first_party,
                       const std::string& cookie_line,
                       content::ResourceContext* context,
                       int render_process_id,
-                      int render_view_id,
+                      int render_frame_id,
                       net::CookieOptions* options);
 
  private:
index d14f44f..404dd63 100644 (file)
@@ -59,13 +59,13 @@ XWalkRequestInterceptor::QueryForInterceptedRequestData(
     const GURL& location,
     net::URLRequest* request) const {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  int render_process_id, render_view_id;
+  int render_process_id, render_frame_id;
   if (!ResourceRequestInfo::GetRenderFrameForRequest(
-      request, &render_process_id, &render_view_id))
+      request, &render_process_id, &render_frame_id))
     return scoped_ptr<InterceptedRequestData>();
 
   scoped_ptr<XWalkContentsIoThreadClient> io_thread_client =
-    XWalkContentsIoThreadClient::FromID(render_process_id, render_view_id);
+    XWalkContentsIoThreadClient::FromID(render_process_id, render_frame_id);
 
   if (!io_thread_client.get())
     return scoped_ptr<InterceptedRequestData>();
index e1c7bad..bf847fc 100644 (file)
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/path_service.h"
+#include "components/visitedlink/browser/visitedlink_master.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/storage_partition.h"
@@ -68,6 +69,9 @@ class RuntimeContext::RuntimeResourceContext : public content::ResourceContext {
 RuntimeContext::RuntimeContext()
   : resource_context_(new RuntimeResourceContext) {
   InitWhileIOAllowed();
+#if defined(OS_ANDROID)
+  InitVisitedLinkMaster();
+#endif
 }
 
 RuntimeContext::~RuntimeContext() {
@@ -229,6 +233,25 @@ void RuntimeContext::SetCSPString(const std::string& csp) {
 std::string RuntimeContext::GetCSPString() const {
   return csp_;
 }
+
+void RuntimeContext::InitVisitedLinkMaster() {
+  visitedlink_master_.reset(
+      new visitedlink::VisitedLinkMaster(this, this, false));
+  visitedlink_master_->Init();
+}
+
+void RuntimeContext::AddVisitedURLs(const std::vector<GURL>& urls) {
+  DCHECK(visitedlink_master_);
+  visitedlink_master_->AddURLs(urls);
+}
+
+void RuntimeContext::RebuildTable(
+    const scoped_refptr<URLEnumerator>& enumerator) {
+  // XWalkView rebuilds from XWalkWebChromeClient.getVisitedHistory. The client
+  // can change in the lifetime of this XWalkView and may not yet be set here.
+  // Therefore this initialization path is not used.
+  enumerator->OnComplete(true);
+}
 #endif
 
 }  // namespace xwalk
index a1120e4..37ededa 100644 (file)
@@ -9,10 +9,13 @@
 #include <string>
 #endif
 
+#include <vector>
+
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "components/visitedlink/browser/visitedlink_delegate.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/geolocation_permission_context.h"
@@ -25,12 +28,21 @@ namespace content {
 class DownloadManagerDelegate;
 }
 
+namespace visitedlink {
+class VisitedLinkMaster;
+}
+
 namespace xwalk {
 
 class RuntimeDownloadManagerDelegate;
 class RuntimeURLRequestContextGetter;
 
-class RuntimeContext : public content::BrowserContext {
+class RuntimeContext
+    : public content::BrowserContext
+#if defined(OS_ANDROID)
+      , public visitedlink::VisitedLinkDelegate
+#endif
+{
  public:
   RuntimeContext();
   virtual ~RuntimeContext();
@@ -88,6 +100,11 @@ class RuntimeContext : public content::BrowserContext {
 #if defined(OS_ANDROID)
   void SetCSPString(const std::string& csp);
   std::string GetCSPString() const;
+  // These methods map to Add methods in visitedlink::VisitedLinkMaster.
+  void AddVisitedURLs(const std::vector<GURL>& urls);
+  // visitedlink::VisitedLinkDelegate implementation.
+  virtual void RebuildTable(
+      const scoped_refptr<URLEnumerator>& enumerator) OVERRIDE;
 #endif
 
  private:
@@ -97,6 +114,11 @@ class RuntimeContext : public content::BrowserContext {
   // allowed on the current thread.
   void InitWhileIOAllowed();
 
+#if defined(OS_ANDROID)
+  // Reset visitedlink master and initialize it.
+  void InitVisitedLinkMaster();
+#endif
+
   scoped_ptr<RuntimeResourceContext> resource_context_;
   scoped_refptr<RuntimeDownloadManagerDelegate> download_manager_delegate_;
   scoped_refptr<RuntimeURLRequestContextGetter> url_request_getter_;
@@ -104,7 +126,9 @@ class RuntimeContext : public content::BrowserContext {
        geolocation_permission_context_;
 #if defined(OS_ANDROID)
   std::string csp_;
+  scoped_ptr<visitedlink::VisitedLinkMaster> visitedlink_master_;
 #endif
+
   DISALLOW_COPY_AND_ASSIGN(RuntimeContext);
 };
 
index 9ff0627..2452dcd 100644 (file)
@@ -21,9 +21,11 @@ namespace xwalk {
 NativeAppWindowTizen::NativeAppWindowTizen(
     const NativeAppWindow::CreateParams& create_params)
     : NativeAppWindowViews(create_params),
+#if defined(OS_TIZEN_MOBILE)
       indicator_widget_(new TizenSystemIndicatorWidget()),
+      indicator_container_(new WidgetContainerView(indicator_widget_)),
+#endif
       allowed_orientations_(ANY) {
-  indicator_container_.reset(new WidgetContainerView(indicator_widget_));
 }
 
 void NativeAppWindowTizen::Initialize() {
@@ -59,9 +61,11 @@ void NativeAppWindowTizen::ViewHierarchyChanged(
     const ViewHierarchyChangedDetails& details) {
   if (details.is_add && details.child == this) {
     NativeAppWindowViews::ViewHierarchyChanged(details);
+#if defined(OS_TIZEN_MOBILE)
     indicator_widget_->Initialize(GetNativeWindow());
     top_view_layout()->set_top_view(indicator_container_.get());
     AddChildView(indicator_container_.get());
+#endif
   }
 }
 
@@ -224,7 +228,10 @@ void NativeAppWindowTizen::ApplyDisplayRotation() {
   if (!root_window->IsVisible())
     return;
   UpdateTopViewOverlay();
+
+#if defined(OS_TIZEN_MOBILE)
   indicator_widget_->SetDisplay(display_);
+#endif
   root_window->SetTransform(GetRotationTransform());
 }
 
index aa7e764..cac7154 100644 (file)
@@ -58,6 +58,7 @@ class NativeAppWindowTizen
   gfx::Display::Rotation GetClosestAllowedRotation(
       gfx::Display::Rotation) const;
 
+#if defined(OS_TIZEN_MOBILE)
   // The system indicator is implemented as a widget because it needs to
   // receive events and may also be an overlay on top of the rest of the
   // content, regular views do not support this. We add it to the container,
@@ -66,6 +67,8 @@ class NativeAppWindowTizen
   // The |indicator_widget_| is owned by the WidgetContainerView.
   TizenSystemIndicatorWidget* indicator_widget_;
   scoped_ptr<WidgetContainerView> indicator_container_;
+#endif
+
   gfx::Display display_;
   OrientationMask allowed_orientations_;
 
index 96177a0..0e1506b 100644 (file)
@@ -18,7 +18,7 @@
 #include "ui/views/window/native_frame_view.h"
 #endif
 
-#if defined(OS_TIZEN_MOBILE)
+#if defined(OS_TIZEN)
 #include "xwalk/runtime/browser/ui/native_app_window_tizen.h"
 #endif
 
@@ -294,7 +294,7 @@ void NativeAppWindowViews::OnWidgetBoundsChanged(views::Widget* widget,
 NativeAppWindow* NativeAppWindow::Create(
     const NativeAppWindow::CreateParams& create_params) {
   NativeAppWindowViews* window;
-#if defined(OS_TIZEN_MOBILE)
+#if defined(OS_TIZEN)
   window = new NativeAppWindowTizen(create_params);
 #else
   window = new NativeAppWindowViews(create_params);
index c174005..7122e9e 100644 (file)
@@ -61,7 +61,6 @@ GURL GetURLFromCommandLine(const CommandLine& command_line) {
 
 namespace xswitches {
 // Redefine settings not exposed by content module.
-const char kEnableViewport[] = "enable-viewport";
 const char kEnableOverlayScrollbars[] = "enable-overlay-scrollbars";
 }
 
@@ -91,7 +90,8 @@ XWalkBrowserMainParts::~XWalkBrowserMainParts() {
 
 void XWalkBrowserMainParts::PreMainMessageLoopStart() {
   CommandLine* command_line = CommandLine::ForCurrentProcess();
-  command_line->AppendSwitch(xswitches::kEnableViewport);
+  command_line->AppendSwitch(switches::kEnableViewport);
+  command_line->AppendSwitch(switches::kEnableViewportMeta);
 
   command_line->AppendSwitch(xswitches::kEnableOverlayScrollbars);
 
index 363b412..8fdcccc 100644 (file)
@@ -16,6 +16,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/show_desktop_notification_params.h"
+#include "net/ssl/ssl_info.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "xwalk/extensions/common/xwalk_extension_switches.h"
 #include "xwalk/runtime/browser/xwalk_browser_main_parts.h"
 #endif
 
 #if defined(OS_TIZEN)
+#include "xwalk/application/browser/application_system.h"
+#include "xwalk/application/browser/application_service.h"
+#include "xwalk/application/browser/application.h"
+#include "xwalk/application/common/application_manifest_constants.h"
+#include "xwalk/application/common/manifest_handlers/navigation_handler.h"
+#include "xwalk/application/common/constants.h"
+#include "xwalk/runtime/browser/runtime_platform_util.h"
 #include "xwalk/runtime/browser/xwalk_browser_main_parts_tizen.h"
 #endif
 
@@ -157,7 +165,7 @@ bool XWalkContentBrowserClient::AllowGetCookie(
     const net::CookieList& cookie_list,
     content::ResourceContext* context,
     int render_process_id,
-    int render_view_id) {
+    int render_frame_id) {
 #if defined(OS_ANDROID)
   return XWalkCookieAccessPolicy::GetInstance()->AllowGetCookie(
       url,
@@ -165,7 +173,7 @@ bool XWalkContentBrowserClient::AllowGetCookie(
       cookie_list,
       context,
       render_process_id,
-      render_view_id);
+      render_frame_id);
 #else
   return true;
 #endif
@@ -177,7 +185,7 @@ bool XWalkContentBrowserClient::AllowSetCookie(
     const std::string& cookie_line,
     content::ResourceContext* context,
     int render_process_id,
-    int render_view_id,
+    int render_frame_id,
     net::CookieOptions* options) {
 #if defined(OS_ANDROID)
   return XWalkCookieAccessPolicy::GetInstance()->AllowSetCookie(
@@ -186,13 +194,42 @@ bool XWalkContentBrowserClient::AllowSetCookie(
       cookie_line,
       context,
       render_process_id,
-      render_view_id,
+      render_frame_id,
       options);
 #else
   return true;
 #endif
 }
 
+void XWalkContentBrowserClient::AllowCertificateError(
+    int render_process_id,
+    int render_frame_id,
+    int cert_error,
+    const net::SSLInfo& ssl_info,
+    const GURL& request_url,
+    ResourceType::Type resource_type,
+    bool overridable,
+    bool strict_enforcement,
+    const base::Callback<void(bool)>& callback,
+    content::CertificateRequestResultType* result) {
+  // Currently only Android handles it.
+  // TODO(yongsheng): applies it for other platforms?
+#if defined(OS_ANDROID)
+  XWalkContentsClientBridgeBase* client =
+      XWalkContentsClientBridgeBase::FromRenderFrameID(render_process_id,
+          render_frame_id);
+  bool cancel_request = true;
+  if (client)
+    client->AllowCertificateError(cert_error,
+                                  ssl_info.cert.get(),
+                                  request_url,
+                                  callback,
+                                  &cancel_request);
+  if (cancel_request)
+    *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
+#endif
+}
+
 void XWalkContentBrowserClient::RequestDesktopNotificationPermission(
     const GURL& source_origin,
     int callback_context,
@@ -219,7 +256,8 @@ void XWalkContentBrowserClient::ShowDesktopNotification(
     bool worker) {
 #if defined(OS_ANDROID)
   XWalkContentsClientBridgeBase* bridge =
-      XWalkContentsClientBridgeBase::FromID(render_process_id, render_view_id);
+      XWalkContentsClientBridgeBase::FromRenderViewID(render_process_id,
+          render_view_id);
   bridge->ShowNotification(params, worker, render_process_id, render_view_id);
 #endif
 }
@@ -230,35 +268,14 @@ void XWalkContentBrowserClient::CancelDesktopNotification(
     int notification_id) {
 #if defined(OS_ANDROID)
   XWalkContentsClientBridgeBase* bridge =
-      XWalkContentsClientBridgeBase::FromID(render_process_id, render_view_id);
+      XWalkContentsClientBridgeBase::FromRenderViewID(render_process_id,
+          render_view_id);
   bridge->CancelNotification(
       notification_id, render_process_id, render_view_id);
 #endif
 }
 
 #if defined(OS_ANDROID)
-void XWalkContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
-    const CommandLine& command_line,
-    int child_process_id,
-    std::vector<content::FileDescriptorInfo>* mappings) {
-  int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
-  base::FilePath pak_file;
-  bool r = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file);
-  CHECK(r);
-  pak_file = pak_file.Append(FILE_PATH_LITERAL("paks"));
-  pak_file = pak_file.Append(FILE_PATH_LITERAL(kXWalkPakFilePath));
-
-  base::PlatformFile f =
-      base::CreatePlatformFile(pak_file, flags, NULL, NULL);
-  if (f == base::kInvalidPlatformFileValue) {
-    NOTREACHED() << "Failed to open file when creating renderer process: "
-                 << "xwalk.pak";
-  }
-  mappings->push_back(
-      content::FileDescriptorInfo(kXWalkPakDescriptor,
-                                  base::FileDescriptor(f, true)));
-}
-
 void XWalkContentBrowserClient::ResourceDispatcherHostCreated() {
   RuntimeResourceDispatcherHostDelegateAndroid::
   ResourceDispatcherHostCreated();
@@ -270,4 +287,51 @@ content::SpeechRecognitionManagerDelegate*
   return new xwalk::XWalkSpeechRecognitionManagerDelegate();
 }
 
+#if defined(OS_TIZEN)
+bool XWalkContentBrowserClient::CanCommitURL(
+    content::RenderProcessHost* process_host, const GURL& url) {
+  application::Application* app = xwalk_runner_->app_system()->
+      application_service()->GetApplicationByRenderHostID(
+          process_host->GetID());
+  DCHECK(app);
+  const application::ApplicationData* app_data =app->data();
+  if (!app_data->HasCSPDefined() ||
+      (url.SchemeIs(application::kApplicationScheme) &&
+       url.host() == app_data->ID()))
+    return true;
+
+  application::NavigationInfo* info = static_cast<application::NavigationInfo*>(
+      app_data->GetManifestData(application_widget_keys::kAllowNavigationKey));
+  if (!info || !url.SchemeIsHTTPOrHTTPS()) {
+    LOG(INFO) << "[Block] Navigation link: " << url.spec();
+    // FIXME: Blocked navigation link should be opened in system web browser,
+    // add corresponding code like this:
+    // platform_util::OpenExternal(url);
+    return false;
+  }
+
+  // Check whether the navigation url domain is listed in WGT <allow-navigation>
+  // element, if yes, display it in web application, otherwise block the
+  // request.
+  const std::vector<std::string>& allowed_list = info->GetAllowedDomains();
+  for (std::vector<std::string>::const_iterator it = allowed_list.begin();
+       it != allowed_list.end(); ++it) {
+    if ((*it).find("*.") == 0 &&
+        url.DomainIs((*it).substr(2).c_str())) {
+      LOG(INFO) << "[Allow] Navigation link: " << url.spec();
+      return true;
+    }
+
+    if (url.host() == *it) {
+      LOG(INFO) << "[Allow] Navigation link: " << url.spec();
+      return true;
+    }
+  }
+  LOG(INFO) << "[Block] navigation link: " << url.spec();
+  // FIXME: Should open blocked link in system web browser, need to add:
+  // platform_util::OpenExternal(url);
+  return false;
+}
+#endif
+
 }  // namespace xwalk
index 32bf4c5..d5fc672 100644 (file)
@@ -65,15 +65,27 @@ class XWalkContentBrowserClient : public content::ContentBrowserClient {
                               const net::CookieList& cookie_list,
                               content::ResourceContext* context,
                               int render_process_id,
-                              int render_view_id) OVERRIDE;
+                              int render_frame_id) OVERRIDE;
   virtual bool AllowSetCookie(const GURL& url,
                               const GURL& first_party,
                               const std::string& cookie_line,
                               content::ResourceContext* context,
                               int render_process_id,
-                              int render_view_id,
+                              int render_frame_id,
                               net::CookieOptions* options) OVERRIDE;
 
+  virtual void AllowCertificateError(
+      int render_process_id,
+      int render_frame_id,
+      int cert_error,
+      const net::SSLInfo& ssl_info,
+      const GURL& request_url,
+      ResourceType::Type resource_type,
+      bool overridable,
+      bool strict_enforcement,
+      const base::Callback<void(bool)>& callback,
+      content::CertificateRequestResultType* result) OVERRIDE;
+
   virtual content::SpeechRecognitionManagerDelegate*
       GetSpeechRecognitionManagerDelegate() OVERRIDE;
 
@@ -96,12 +108,12 @@ class XWalkContentBrowserClient : public content::ContentBrowserClient {
       int render_process_id,
       int render_view_id,
       int notification_id) OVERRIDE;
+#if defined(OS_TIZEN)
+  virtual bool CanCommitURL(
+      content::RenderProcessHost* process_host, const GURL& url) OVERRIDE;
+#endif
 
 #if defined(OS_ANDROID)
-  virtual void GetAdditionalMappedFilesForChildProcess(
-      const CommandLine& command_line,
-      int child_process_id,
-      std::vector<content::FileDescriptorInfo>* mappings) OVERRIDE;
   virtual void ResourceDispatcherHostCreated();
 #endif
   XWalkBrowserMainParts* main_parts() { return main_parts_; }
diff --git a/src/xwalk/runtime/common/xwalk_common_message_generator.cc b/src/xwalk/runtime/common/xwalk_common_message_generator.cc
new file mode 100644 (file)
index 0000000..01354c9
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 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.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "xwalk/runtime/common/xwalk_common_message_generator.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "xwalk/runtime/common/xwalk_common_message_generator.h"  // NOLINT
+
+// Generate destructors.
+#include "ipc/struct_destructor_macros.h"
+#include "xwalk/runtime/common/xwalk_common_message_generator.h"  // NOLINT
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#include "xwalk/runtime/common/xwalk_common_message_generator.h"  // NOLINT
+}  // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#include "xwalk/runtime/common/xwalk_common_message_generator.h"  // NOLINT
+}  // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#include "xwalk/runtime/common/xwalk_common_message_generator.h"  // NOLINT
+}  // namespace IPC
diff --git a/src/xwalk/runtime/common/xwalk_common_message_generator.h b/src/xwalk/runtime/common/xwalk_common_message_generator.h
new file mode 100644 (file)
index 0000000..0b3b7fe
--- /dev/null
@@ -0,0 +1,7 @@
+// 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.
+
+// Multiply-included file, hence no include guard.
+
+#include "xwalk/runtime/common/xwalk_common_messages.h"
diff --git a/src/xwalk/runtime/common/xwalk_common_messages.cc b/src/xwalk/runtime/common/xwalk_common_messages.cc
new file mode 100644 (file)
index 0000000..fb8e2c3
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "xwalk/runtime/common/xwalk_common_messages.h"
+
+namespace IPC {
+
+// TODO(upstream): - add enums and custom IPC traits here when needed.
+
+}  // namespace IPC
diff --git a/src/xwalk/runtime/common/xwalk_common_messages.h b/src/xwalk/runtime/common/xwalk_common_messages.h
new file mode 100644 (file)
index 0000000..4afe4eb
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+// Multiply-included file, no traditional include guard.
+#include "content/public/common/common_param_traits.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_platform_file.h"
+#include "url/gurl.h"
+
+// Singly-included section for enums and custom IPC traits.
+#ifndef XWALK_RUNTIME_COMMON_XWALK_COMMON_MESSAGES_H_
+#define XWALK_RUNTIME_COMMON_XWALK_COMMON_MESSAGES_H_
+
+namespace IPC {
+
+// TODO(upstream): - add enums and custom IPC traits here when needed.
+
+}  // namespace IPC
+
+#endif  // XWALK_RUNTIME_COMMON_XWALK_COMMON_MESSAGES_H_
+
+#define IPC_MESSAGE_START ViewMsgStart
+
+//-----------------------------------------------------------------------------
+// RenderView messages
+// These are messages sent from the browser to the renderer process.
+
+IPC_MESSAGE_CONTROL3(ViewMsg_SetAccessWhiteList,  // NOLINT
+                     GURL /* source */,
+                     GURL /* dest */,
+                     bool /* allow_subdomains */)
+
+IPC_MESSAGE_CONTROL0(ViewMsg_EnableWarpMode)  // NOLINT
index 06de4ae..0727328 100644 (file)
@@ -78,6 +78,11 @@ bool PathProvider(int key, base::FilePath* path) {
       cur = cur.Append(FILE_PATH_LITERAL("test"));
       cur = cur.Append(FILE_PATH_LITERAL("data"));
       break;
+    case xwalk::DIR_WGT_STORAGE_PATH:
+      if (!GetXWalkDataPath(&cur))
+        return false;
+      cur = cur.Append(FILE_PATH_LITERAL("Widget Storage"));
+      break;
     default:
       return false;
   }
index e007095..88520cc 100644 (file)
@@ -15,6 +15,7 @@ enum {
   DIR_DATA_PATH = PATH_START,  // Directory where the cache and local storage
                                // data resides.
   DIR_TEST_DATA,               // Directory where unit test data resides.
+  DIR_WGT_STORAGE_PATH,        // Directory where widget storage data resides.
   PATH_END
 };
 
index e856a30..554a963 100644 (file)
@@ -5,9 +5,12 @@
 #include "xwalk/runtime/renderer/xwalk_content_renderer_client.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "components/visitedlink/renderer/visitedlink_slave.h"
 #include "content/public/renderer/render_thread.h"
+#include "grit/xwalk_application_resources.h"
 #include "grit/xwalk_sysapps_resources.h"
 #include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
 #include "xwalk/application/common/constants.h"
 #include "xwalk/application/renderer/application_native_module.h"
@@ -17,6 +20,8 @@
 #include "xwalk/runtime/renderer/android/xwalk_permission_client.h"
 #include "xwalk/runtime/renderer/android/xwalk_render_process_observer.h"
 #include "xwalk/runtime/renderer/android/xwalk_render_view_ext.h"
+#else
+#include "third_party/WebKit/public/web/WebFrame.h"
 #endif
 
 #if defined(OS_TIZEN_MOBILE)
@@ -51,10 +56,12 @@ void XWalkContentRendererClient::RenderThreadStarted() {
   blink::WebSecurityPolicy::registerURLSchemeAsSecure(application_scheme);
   blink::WebSecurityPolicy::registerURLSchemeAsCORSEnabled(application_scheme);
 
-#if defined(OS_ANDROID)
   content::RenderThread* thread = content::RenderThread::Get();
   xwalk_render_process_observer_.reset(new XWalkRenderProcessObserver);
   thread->AddObserver(xwalk_render_process_observer_.get());
+#if defined(OS_ANDROID)
+  visited_link_slave_.reset(new visitedlink::VisitedLinkSlave);
+  thread->AddObserver(visited_link_slave_.get());
 #endif
 }
 
@@ -76,6 +83,10 @@ void XWalkContentRendererClient::DidCreateScriptContext(
     blink::WebFrame* frame, v8::Handle<v8::Context> context,
     int extension_group, int world_id) {
   extension_controller_->DidCreateScriptContext(frame, context);
+#if !defined(OS_ANDROID)
+  xwalk_render_process_observer_->DidCreateScriptContext(
+      frame, context, extension_group, world_id);
+#endif
 }
 
 void XWalkContentRendererClient::WillReleaseScriptContext(
@@ -93,6 +104,42 @@ void XWalkContentRendererClient::DidCreateModuleSystem(
   module_system->RegisterNativeModule("sysapps_promise",
       extensions::CreateJSModuleFromResource(
           IDR_XWALK_SYSAPPS_COMMON_PROMISE_API));
+  module_system->RegisterNativeModule("widget_common",
+      extensions::CreateJSModuleFromResource(
+          IDR_XWALK_APPLICATION_WIDGET_COMMON_API));
+}
+
+#if defined(OS_ANDROID)
+unsigned long long XWalkContentRendererClient::VisitedLinkHash(
+    const char* canonical_url, size_t length) {
+  return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
 }
 
+bool XWalkContentRendererClient::IsLinkVisited(unsigned long long link_hash) {
+  return visited_link_slave_->IsVisited(link_hash);
+}
+#endif
+
+bool XWalkContentRendererClient::WillSendRequest(blink::WebFrame* frame,
+                     content::PageTransition transition_type,
+                     const GURL& url,
+                     const GURL& first_party_for_cookies,
+                     GURL* new_url) {
+#if defined(OS_ANDROID)
+  return false;
+#else
+  if (!xwalk_render_process_observer_->IsWarpMode())
+    return false;
+  GURL origin_url(frame->document().url());
+  if (origin_url.spec().empty() ||
+     frame->document().securityOrigin().canRequest(url)) {
+    LOG(INFO) << "[PASS] " << origin_url.spec() << " request " << url.spec();
+    return false;
+  }
+
+  LOG(INFO) << "[BLOCK] " << origin_url.spec() << " request " << url.spec();
+  *new_url = GURL();
+  return true;
+#endif
+}
 }  // namespace xwalk
index 1fdb425..ee9852a 100644 (file)
@@ -8,8 +8,18 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
+#include "content/public/common/page_transition_types.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "xwalk/extensions/renderer/xwalk_extension_renderer_controller.h"
+#if defined(OS_ANDROID)
+#include "xwalk/runtime/renderer/android/xwalk_render_process_observer.h"
+#else
+#include "xwalk/runtime/renderer/xwalk_render_process_observer_generic.h"
+#endif
+
+namespace visitedlink {
+class VisitedLinkSlave;
+}
 
 namespace xwalk {
 
@@ -36,6 +46,17 @@ class XWalkContentRendererClient
   virtual void WillReleaseScriptContext(blink::WebFrame* frame,
                                         v8::Handle<v8::Context>,
                                         int world_id) OVERRIDE;
+#if defined(OS_ANDROID)
+  virtual unsigned long long VisitedLinkHash(const char* canonical_url,
+                                             size_t length) OVERRIDE;
+  virtual bool IsLinkVisited(unsigned long long link_hash) OVERRIDE;
+#endif
+
+  virtual bool WillSendRequest(blink::WebFrame* frame,
+                               content::PageTransition transition_type,
+                               const GURL& url,
+                               const GURL& first_party_for_cookies,
+                               GURL* new_url) OVERRIDE;
 
  private:
   // XWalkExtensionRendererController::Delegate implementation.
@@ -45,8 +66,9 @@ class XWalkContentRendererClient
   scoped_ptr<extensions::XWalkExtensionRendererController>
       extension_controller_;
 
-#if defined(OS_ANDROID)
   scoped_ptr<XWalkRenderProcessObserver> xwalk_render_process_observer_;
+#if defined(OS_ANDROID)
+  scoped_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(XWalkContentRendererClient);
diff --git a/src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.cc b/src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.cc
new file mode 100644 (file)
index 0000000..14139d3
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/renderer/xwalk_render_process_observer_generic.h"
+
+#include <vector>
+
+#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "xwalk/runtime/common/xwalk_common_messages.h"
+
+
+namespace xwalk {
+namespace {
+struct AccessWhitelistItem {
+  AccessWhitelistItem(
+      const GURL& source, const GURL& dest, bool allow_subdomains);
+  GURL source_;
+  GURL dest_;
+  bool allow_subdomains_;
+};
+
+AccessWhitelistItem::AccessWhitelistItem(
+    const GURL& source, const GURL& dest, bool allow_subdomains)
+    : source_(source),
+      dest_(dest),
+      allow_subdomains_(allow_subdomains) {
+}
+
+std::vector<AccessWhitelistItem> access_whitelist;
+
+void AddAccessWhiteListEntry(
+    const GURL& source, const GURL& dest, bool allow_subdomains) {
+  blink::WebSecurityPolicy::addOriginAccessWhitelistEntry(
+      source.GetOrigin(),
+      blink::WebString::fromUTF8(dest.scheme()),
+      blink::WebString::fromUTF8(dest.HostNoBrackets()),
+      allow_subdomains);
+}
+}  // namespace
+
+XWalkRenderProcessObserver::XWalkRenderProcessObserver()
+    : is_webkit_initialized_(false),
+      is_warp_mode_(false) {
+}
+
+XWalkRenderProcessObserver::~XWalkRenderProcessObserver() {
+}
+
+bool XWalkRenderProcessObserver::OnControlMessageReceived(
+    const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(XWalkRenderProcessObserver, message)
+    IPC_MESSAGE_HANDLER(ViewMsg_SetAccessWhiteList, OnSetAccessWhiteList)
+    IPC_MESSAGE_HANDLER(ViewMsg_EnableWarpMode, OnEnableWarpMode)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void XWalkRenderProcessObserver::WebKitInitialized() {
+  is_webkit_initialized_ = true;
+}
+
+void XWalkRenderProcessObserver::OnRenderProcessShutdown() {
+  is_webkit_initialized_ = false;
+}
+
+void XWalkRenderProcessObserver::DidCreateScriptContext(
+    blink::WebFrame* frame, v8::Handle<v8::Context> context,
+    int extension_group, int world_id) {
+  for (std::vector<AccessWhitelistItem>::iterator it = access_whitelist.begin();
+       it != access_whitelist.end(); ++it)
+    AddAccessWhiteListEntry(it->source_, it->dest_, it->allow_subdomains_);
+
+  access_whitelist.clear();
+}
+
+void XWalkRenderProcessObserver::OnSetAccessWhiteList(const GURL& source,
+                                                      const GURL& dest,
+                                                      bool allow_subdomains) {
+  if (is_webkit_initialized_)
+    AddAccessWhiteListEntry(source, dest, allow_subdomains);
+  else
+    access_whitelist.push_back(
+        AccessWhitelistItem(source, dest, allow_subdomains));
+}
+
+void XWalkRenderProcessObserver::OnEnableWarpMode() {
+  is_warp_mode_ = true;
+}
+
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.h b/src/xwalk/runtime/renderer/xwalk_render_process_observer_generic.h
new file mode 100644 (file)
index 0000000..3592be0
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_RENDERER_XWALK_RENDER_PROCESS_OBSERVER_GENERIC_H_
+#define XWALK_RUNTIME_RENDERER_XWALK_RENDER_PROCESS_OBSERVER_GENERIC_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "content/public/renderer/render_process_observer.h"
+#include "url/gurl.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+class WebFrame;
+}  // namespace blink
+
+namespace xwalk {
+
+// FIXME: Using filename "xwalk_render_process_observer_generic.cc(h)" temporary
+// , due to the conflict filename with Android port.
+// A RenderViewObserver implementation used for handling XWalkView
+// specific render-process wide IPC messages.
+class XWalkRenderProcessObserver : public content::RenderProcessObserver {
+ public:
+  XWalkRenderProcessObserver();
+  virtual ~XWalkRenderProcessObserver();
+
+  void DidCreateScriptContext(
+      blink::WebFrame* frame,  v8::Handle<v8::Context> context,
+      int extension_group, int world_id);
+
+  // content::RenderProcessObserver implementation.
+  virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+  virtual void WebKitInitialized() OVERRIDE;
+  virtual void OnRenderProcessShutdown() OVERRIDE;
+
+  bool IsWarpMode() const { return is_warp_mode_; }
+
+ private:
+  void OnSetAccessWhiteList(
+      const GURL& source, const GURL& dest, bool allow_subdomains);
+  void OnEnableWarpMode();
+
+  bool is_webkit_initialized_;
+  bool is_warp_mode_;
+};
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_RENDERER_XWALK_RENDER_PROCESS_OBSERVER_GENERIC_H_
index 3b6e29a..58c4775 100644 (file)
@@ -28,14 +28,16 @@ namespace device_capabilities {
   dictionary DisplayUnit {
     DOMString id;
     DOMString name;
-    boolean isPrimary;
-    boolean isInternal;
-    long dpiX;
-    long dpiY;
+    boolean primary;
+    boolean external;
+    long deviceXDPI;
+    long deviceYDPI;
     long width;
     long height;
     long availWidth;
     long availHeight;
+    long colorDepth;
+    long pixelDepth;
   };
 
   dictionary SystemDisplay {
index db66052..335f94f 100644 (file)
             if (typeof info.displays[i].name != "string")
               reportFail("Display name is not a string.");
 
-            if (typeof info.displays[i].isPrimary != "boolean")
+            if (typeof info.displays[i].primary != "boolean")
               reportFail("Display type is not a boolean.");
 
-            if (typeof info.displays[i].isInternal != "boolean")
+            if (typeof info.displays[i].external != "boolean")
               reportFail("Display type is not a boolean.");
 
-            if (typeof info.displays[i].dpiX != "number")
-              reportFail("Display dpiX must be a number.");
+            if (typeof info.displays[i].deviceXDPI != "number")
+              reportFail("Display deviceXDPI must be a number.");
 
-            if (typeof info.displays[i].dpiY != "number")
-              reportFail("Display dpiY must be a number.");
+            if (typeof info.displays[i].deviceYDPI != "number")
+              reportFail("Display deviceYDPI must be a number.");
 
             if (typeof info.displays[i].width != "number")
               reportFail("Display width must be a number.");
 
             if (typeof info.displays[i].availHeight != "number")
               reportFail("Display availHeight must be a number.");
+
+            if (typeof info.displays[i].colorDepth != "number")
+              reportFail("Display colorDepth must be a number.");
+
+            if (typeof info.displays[i].pixelDepth != "number")
+              reportFail("Display pixelDepth must be a number.");
           }
 
           if (document.title != "Fail")
index d657218..5363de8 100644 (file)
@@ -29,18 +29,23 @@ linked_ptr<DisplayUnit> makeDisplayUnit(const gfx::Display& display) {
   // FIXME(YuZhiqiangX): find which field reflects 'name'.
   display_unit->name = "unknown";
 
-  display_unit->is_primary = (display.id() == primary_display_id);
-  display_unit->is_internal = display.IsInternal();
+  display_unit->primary = (display.id() == primary_display_id);
+  display_unit->external = !display.IsInternal();
 
   const float dpi = display.device_scale_factor() * kDpi96;
-  display_unit->dpi_x = static_cast<unsigned int>(dpi);
-  display_unit->dpi_y = static_cast<unsigned int>(dpi);
+  display_unit->device_xdpi = static_cast<unsigned int>(dpi);
+  display_unit->device_ydpi = static_cast<unsigned int>(dpi);
 
   display_unit->width = display.bounds().width();
   display_unit->height = display.bounds().height();
   display_unit->avail_width = display.work_area_size().width();
   display_unit->avail_height = display.work_area_size().height();
 
+  // colorDepth and pixelDepth are constantly set as 24 refer to
+  // http://www.w3.org/TR/cssom-view/#dom-screen-colordepth
+  display_unit->color_depth = 24;
+  display_unit->pixel_depth = 24;
+
   return display_unit;
 }
 
index 1dde5ff..65dca0b 100644 (file)
@@ -47,8 +47,22 @@ namespace raw_socket {
     ReadyState readyState;
   };
 
+  // Events and functions are defined at
+  // udp_socket.idl
+  dictionary UDPSocket {
+    DOMString localAddress;
+    long localPort;
+    DOMString remoteAddress;
+    long remotePort;
+    boolean addressReuse;
+    boolean loopback;
+    long bufferedAmount;
+    ReadyState readyState;
+  };
+
   interface Functions {
     [nodoc] static TCPSocket TCPSocketConstructor(DOMString objectId);
     [nodoc] static TCPServerSocket TCPServerSocketConstructor(DOMString objectId);
+    [nodoc] static UDPSocket UDPSocketConstructor(DOMString objectId);
   };
 };
index 8086be7..510c0ac 100644 (file)
@@ -270,6 +270,138 @@ var TCPServerSocket = function(options) {
 TCPServerSocket.prototype = new common.EventTargetPrototype();
 TCPServerSocket.prototype.constructor = TCPServerSocket;
 
+// UDPSocket interface.
+//
+// TODO(tmpsantos): We are currently not throwing any exceptions
+// neither validating the input parameters.
+//
+var UDPSocket = function(options) {
+  common.BindingObject.call(this, common.getUniqueId());
+  common.EventTarget.call(this);
+
+  internal.postMessage("UDPSocketConstructor", [this._id]);
+
+  var options = options || {};
+
+  if (!options.localAddress)
+    options.localAddress = "";
+  if (!options.localPort)
+    options.localPort = 0;
+  if (!options.remoteAddress)
+    options.remoteAddress = "";
+  if (!options.remotePort)
+    options.remotePort = 0;
+  if (!options.addressReuse)
+    options.addressReuse = true;
+  if (!options.loopback)
+    options.loopback = false;
+
+  this._addMethod("_close");
+  this._addMethod("suspend");
+  this._addMethod("resume");
+  this._addMethod("joinMulticast");
+  this._addMethod("leaveMulticast");
+  this._addMethod("_sendString");
+
+  function MessageEvent(type, data) {
+    this.type = type;
+    this.data = data.data;
+    this.remotePort = data.remotePort;
+    this.remoteAddress = data.remoteAddress;
+  }
+
+  this._addEvent("open");
+  this._addEvent("drain");
+  this._addEvent("error");
+  this._addEvent("message", MessageEvent);
+
+  function sendWrapper(data, remoteAddress, remotePort) {
+    this._sendString(data, remoteAddress, remotePort);
+
+    // FIXME(tmpsantos): The spec says that send() should always
+    // return if you can keep sending data. This can only be
+    // verified in the native implementation, which makes this
+    // call sync. We are returning always true here to keep the
+    // implementation async.
+    return true;
+  };
+
+  function closeWrapper(data) {
+    if (this._readyStateObserver.readyState == "closed")
+      return;
+
+    this._readyStateObserver.readyState = "closing";
+    this._close();
+  };
+
+  Object.defineProperties(this, {
+    "_readyStateObserver": {
+      value: new ReadyStateObserver(this._id, "opening"),
+    },
+    "_readyStateObserverDeleter": {
+      value: v8tools.lifecycleTracker(),
+    },
+    "send": {
+      value: sendWrapper,
+      enumerable: true,
+    },
+    "close": {
+      value: closeWrapper,
+      enumerable: true,
+    },
+    "remoteAddress": {
+      value: options.remoteAddress,
+      enumerable: true,
+    },
+    "remotePort": {
+      value: options.remotePort,
+      enumerable: true,
+    },
+    "localAddress": {
+      value: options.localAddress,
+      enumerable: true,
+    },
+    "localPort": {
+      value: options.localPort,
+      enumerable: true,
+    },
+    "addressReuse": {
+      value: options.addressReuse,
+      enumerable: true,
+    },
+    "loopback": {
+      value: options.loopback,
+      enumerable: true,
+    },
+    "bufferedAmount": {
+      value: 0,
+      enumerable: true,
+    },
+    "readyState": {
+      get: function() { return this._readyStateObserver.readyState; },
+      enumerable: true,
+    },
+  });
+
+  var watcher = this._readyStateObserver;
+  this._readyStateObserverDeleter.destructor = function() {
+    watcher.destructor();
+  };
+
+  // This is needed, otherwise events like "error" can get fired before
+  // we give the user a chance to register a listener.
+  function delayedInitialization(obj) {
+    obj._postMessage("init", [options]);
+  };
+
+  this._registerLifecycleTracker();
+  setTimeout(delayedInitialization, 0, this);
+};
+
+UDPSocket.prototype = new common.EventTargetPrototype();
+UDPSocket.prototype.constructor = UDPSocket;
+
 // Exported API.
 exports.TCPSocket = TCPSocket;
 exports.TCPServerSocket = TCPServerSocket;
+exports.UDPSocket = UDPSocket;
index 2d1a871..f2a6a94 100644 (file)
       var current_test = 0;
       var test_list = [
         memoryManagement,
-        pingPong,
-        serverPortBusy,
+        pingPongTCP,
+        pingPongUDP,
+        serverPortBusyTCP,
+        serverPortBusyUDP,
         endTest
       ];
 
         // initialization is completed, the object will be collected if no
         // variable is keeping a reference to it.
         function runGCandCheck() {
+          // The GC is called here more than once to make sure
+          // all the dangling objects get collected. Calling the GC
+          // one time does not give a guarantee that everything that
+          // can be collected will be collected.
           gc();
-          if (garbageCollectionCount != 2)
-            reportFail("TCPSocket or TCPServerSocket is leaking.");
+          gc();
+          gc();
+
+          if (garbageCollectionCount != 3)
+            reportFail("TCPSocket, TCPServerSocket or UDPSocket is leaking.");
           else
             runNextTest();
         };
@@ -60,7 +69,7 @@
           server.onopen = null;
           server = null;
 
-          if (++eventCount == 2)
+          if (++eventCount == 3)
             setTimeout(runGCandCheck, 0);
         };
 
           client.onopen = null;
           client = null;
 
-          if (++eventCount == 2)
+          if (++eventCount == 3)
+            setTimeout(runGCandCheck, 0);
+        };
+
+        var udp = new api.UDPSocket({localAddress: "127.0.0.1", localPort: 7000});
+        udp.onerror = udp.onopen = nullifyUDP;
+        udp.tracker = v8tools.lifecycleTracker();
+        udp.tracker.destructor = function() {
+          garbageCollectionCount++;
+        };
+
+        function nullifyUDP() {
+          udp.onerror = null;
+          udp.onopen = null;
+          udp = null;
+
+          if (++eventCount == 3)
             setTimeout(runGCandCheck, 0);
         };
       };
       //
       // This is not an API conformance test, it just verifies if the basic
       // functionality works. W3C should provide the former.
-      function pingPong(serverPort) {
+      function pingPongTCP(serverPort) {
         serverPort = serverPort || 5000;
         var serverPortMax = 5020;
         var testData = "Hello World!";
           // The default port might be busy, so we try different ports
           // before reporting failure.
           if (serverPort < serverPortMax)
-            pingPong(++serverPort);
+            pingPongTCP(++serverPort);
           else
             reportFail("Not able to listen at port " + serverPort + ".");
         };
         };
       };
 
-      function serverPortBusy(serverPort) {
+      function pingPongUDP(serverPort) {
+        serverPort = serverPort || 6000;
+        var serverPortMax = 6020;
+        var testData = "Hello World!";
+
+        var server = new api.UDPSocket(
+            {"localAddress": "127.0.0.1", "localPort": serverPort});
+
+        server.onerror = function() {
+          // The default port might be busy, so we try different ports
+          // before reporting failure.
+          if (serverPort < serverPortMax)
+            pingPongUDP(++serverPort);
+          else
+            reportFail("Not able to listen at port " + serverPort + ".");
+        };
+
+        server.onopen = function() {
+          var client = new api.UDPSocket(
+              {remoteAddress: "127.0.0.1", remotePort: serverPort});
+          client.onopen = function() {
+            client.send(testData);
+          };
+
+          client.onerror = function() {
+            reportFail("Not able to connect to port " + serverPort + ".");
+          };
+
+          client.onmessage = function(event) {
+            var view = new Uint8Array(event.data);
+            var data = String.fromCharCode.apply(null, view);
+
+            if (data != testData)
+              reportFail("Invalid data received by the client socket.");
+            else
+              runNextTest();
+          };
+        };
+
+        server.onmessage = function(event) {
+          var view = new Uint8Array(event.data);
+          var data = String.fromCharCode.apply(null, view);
+
+          if (data != testData)
+            reportFail("Invalid data received by server socket.");
+          else
+            server.send(data, event.remoteAddress, event.remotePort);
+        };
+      };
+
+      function serverPortBusy(Socket, serverPort) {
         serverPort = serverPort || 7000;
         var serverPortMax = 7020;
 
-        var server = new api.TCPServerSocket(
+        var server = new Socket(
             {"localAddress": "127.0.0.1", "localPort": serverPort});
 
         server.onerror = function() {
           if (serverPort < serverPortMax)
-            serverPortBusy(++serverPort);
+            serverPortBusy(Socket, ++serverPort);
           else
             reportFail("Not able to listen at port " + serverPort + ".");
         };
 
         server.onopen = function() {
-          var serverShouldFail = new api.TCPServerSocket(
+          var serverShouldFail = new Socket(
               {"localAddress": "127.0.0.1", "localPort": serverPort});
 
           // Should fail, port already in use by another server.
         };
       };
 
+      function serverPortBusyTCP() {
+        serverPortBusy(api.TCPServerSocket);
+      };
+
+      function serverPortBusyUDP() {
+        serverPortBusy(api.UDPSocket);
+      };
+
       runNextTest();
     </script>
   </body>
index fe03277..6235422 100644 (file)
@@ -9,6 +9,7 @@
 #include "xwalk/sysapps/raw_socket/raw_socket.h"
 #include "xwalk/sysapps/raw_socket/tcp_server_socket_object.h"
 #include "xwalk/sysapps/raw_socket/tcp_socket_object.h"
+#include "xwalk/sysapps/raw_socket/udp_socket_object.h"
 
 using namespace xwalk::jsapi::raw_socket; // NOLINT
 
@@ -36,6 +37,9 @@ RawSocketInstance::RawSocketInstance()
   handler_.Register("TCPSocketConstructor",
       base::Bind(&RawSocketInstance::OnTCPSocketConstructor,
                  base::Unretained(this)));
+  handler_.Register("UDPSocketConstructor",
+      base::Bind(&RawSocketInstance::OnUDPSocketConstructor,
+                 base::Unretained(this)));
 }
 
 void RawSocketInstance::HandleMessage(scoped_ptr<base::Value> msg) {
@@ -75,5 +79,19 @@ void RawSocketInstance::OnTCPSocketConstructor(
   store_.AddBindingObject(params->object_id, obj.Pass());
 }
 
+void RawSocketInstance::OnUDPSocketConstructor(
+    scoped_ptr<XWalkExtensionFunctionInfo> info) {
+  scoped_ptr<UDPSocketConstructor::Params>
+      params(UDPSocketConstructor::Params::Create(*info->arguments()));
+
+  if (!params) {
+    LOG(WARNING) << "Malformed parameters passed to " << info->name();
+    return;
+  }
+
+  scoped_ptr<BindingObject> obj(new UDPSocketObject);
+  store_.AddBindingObject(params->object_id, obj.Pass());
+}
+
 }  // namespace sysapps
 }  // namespace xwalk
index 25fedc4..499c54b 100644 (file)
@@ -40,6 +40,7 @@ class RawSocketInstance : public XWalkExtensionInstance {
   void OnTCPServerSocketConstructor(
       scoped_ptr<XWalkExtensionFunctionInfo> info);
   void OnTCPSocketConstructor(scoped_ptr<XWalkExtensionFunctionInfo> info);
+  void OnUDPSocketConstructor(scoped_ptr<XWalkExtensionFunctionInfo> info);
 
   XWalkExtensionFunctionHandler handler_;
   BindingObjectStore store_;
diff --git a/src/xwalk/sysapps/raw_socket/udp_socket.idl b/src/xwalk/sysapps/raw_socket/udp_socket.idl
new file mode 100644 (file)
index 0000000..a4c7101
--- /dev/null
@@ -0,0 +1,49 @@
+// 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.
+
+// RawSocket API - UDPSocket
+namespace udp_socket {
+  dictionary UDPMessageEvent {
+    ArrayBuffer data;
+    DOMString remoteAddress;
+    long remotePort;
+  };
+
+  dictionary UDPOptions {
+    DOMString localAddress;
+    long localPort;
+    DOMString remoteAddress;
+    long remotePort;
+    boolean addressReuse;
+    boolean loopback;
+  };
+
+  interface Events {
+    static void ondrain();
+    static void onopen();
+    static void onerror();
+    static void onmessage();
+  };
+
+  interface Functions {
+    static void close();
+    static void suspend();
+    static void resume();
+    static void joinMulticast(DOMString multicastGroupAddress);
+    static void leaveMulticast(DOMString multicastGroupAddress);
+
+    [nocompile] static boolean send(object data, optional DOMString remoteAddress,
+        optional long remotePort);
+
+    // send() can take up to four different types of arguments. We try to
+    // detect what kind of argument we have and route to a more specialized
+    // handler.
+
+    [nodoc] static boolean sendDOMString(DOMString data,
+        optional DOMString remoteAddress, optional long remotePort);
+
+    [nodoc] static void init(optional UDPOptions options);
+    [nodoc] static void destroy();
+  };
+};
diff --git a/src/xwalk/sysapps/raw_socket/udp_socket_object.cc b/src/xwalk/sysapps/raw_socket/udp_socket_object.cc
new file mode 100644 (file)
index 0000000..bcbeb6f
--- /dev/null
@@ -0,0 +1,276 @@
+// 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/sysapps/raw_socket/udp_socket_object.h"
+
+#include <string.h>
+
+#include "base/logging.h"
+#include "net/base/net_errors.h"
+#include "xwalk/sysapps/raw_socket/udp_socket.h"
+
+using namespace xwalk::jsapi::udp_socket; // NOLINT
+using namespace xwalk::jsapi::raw_socket; // NOLINT
+
+namespace {
+
+const unsigned kBufferSize = 4096;
+
+}  // namespace
+
+namespace xwalk {
+namespace sysapps {
+
+UDPSocketObject::UDPSocketObject()
+    : has_write_pending_(false),
+      is_suspended_(false),
+      is_reading_(false),
+      resolver_(net::HostResolver::CreateDefaultResolver(NULL)),
+      read_buffer_(new net::IOBuffer(kBufferSize)),
+      write_buffer_(new net::IOBuffer(kBufferSize)),
+      single_resolver_(new net::SingleRequestHostResolver(resolver_.get())) {
+  handler_.Register("init",
+      base::Bind(&UDPSocketObject::OnInit, base::Unretained(this)));
+  handler_.Register("_close",
+      base::Bind(&UDPSocketObject::OnClose, base::Unretained(this)));
+  handler_.Register("suspend",
+      base::Bind(&UDPSocketObject::OnSuspend, base::Unretained(this)));
+  handler_.Register("resume",
+      base::Bind(&UDPSocketObject::OnResume, base::Unretained(this)));
+  handler_.Register("joinMulticast",
+      base::Bind(&UDPSocketObject::OnJoinMulticast, base::Unretained(this)));
+  handler_.Register("leaveMulticast",
+      base::Bind(&UDPSocketObject::OnLeaveMulticast, base::Unretained(this)));
+  handler_.Register("_sendString",
+      base::Bind(&UDPSocketObject::OnSendString, base::Unretained(this)));
+}
+
+UDPSocketObject::~UDPSocketObject() {}
+
+void UDPSocketObject::DoRead() {
+  if (!socket_->is_connected())
+    return;
+
+  is_reading_ = true;
+
+  int ret = socket_->RecvFrom(read_buffer_,
+                              kBufferSize,
+                              &from_,
+                              base::Bind(&UDPSocketObject::OnRead,
+                                         base::Unretained(this)));
+
+  if (ret > 0)
+    OnRead(ret);
+}
+
+void UDPSocketObject::OnInit(scoped_ptr<XWalkExtensionFunctionInfo> info) {
+  scoped_ptr<Init::Params> params(Init::Params::Create(*info->arguments()));
+  if (!params) {
+    LOG(WARNING) << "Malformed parameters passed to " << info->name();
+    setReadyState(READY_STATE_CLOSED);
+    DispatchEvent("error");
+    return;
+  }
+
+  socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
+                                   net::RandIntCallback(),
+                                   NULL,
+                                   net::NetLog::Source()));
+
+  if (!params->options) {
+    OnConnectionOpen(net::OK);
+    return;
+  }
+
+  if (!params->options->local_address.empty()) {
+    net::IPAddressNumber ip_number;
+    if (!net::ParseIPLiteralToNumber(params->options->local_address,
+                                     &ip_number)) {
+      LOG(WARNING) << "Invalid IP address " << params->options->local_address;
+      setReadyState(READY_STATE_CLOSED);
+      DispatchEvent("error");
+      return;
+    }
+
+    if (params->options->address_reuse)
+      socket_->AllowAddressReuse();
+
+    net::IPEndPoint end_point(ip_number, params->options->local_port);
+    if (socket_->Bind(end_point) != net::OK) {
+      LOG(WARNING) << "Can't bind to " << end_point.ToString();
+      setReadyState(READY_STATE_CLOSED);
+      DispatchEvent("error");
+      return;
+    }
+
+    DoRead();
+    OnConnectionOpen(net::OK);
+    return;
+  }
+
+  if (params->options->remote_address.empty() ||
+      !params->options->remote_port) {
+    OnConnectionOpen(net::OK);
+    return;
+  }
+
+  net::HostResolver::RequestInfo request_info(net::HostPortPair(
+      params->options->remote_address, params->options->remote_port));
+
+  int ret = single_resolver_->Resolve(
+      request_info,
+      net::DEFAULT_PRIORITY,
+      &addresses_,
+      base::Bind(&UDPSocketObject::OnConnectionOpen,
+                 base::Unretained(this)),
+      net::BoundNetLog());
+
+  if (ret != net::ERR_IO_PENDING)
+    OnConnectionOpen(ret);
+}
+
+void UDPSocketObject::OnClose(scoped_ptr<XWalkExtensionFunctionInfo> info) {
+  socket_.reset();
+}
+
+void UDPSocketObject::OnSuspend(scoped_ptr<XWalkExtensionFunctionInfo> info) {
+  is_suspended_ = true;
+}
+
+void UDPSocketObject::OnResume(scoped_ptr<XWalkExtensionFunctionInfo> info) {
+  is_suspended_ = false;
+}
+
+void UDPSocketObject::OnJoinMulticast(
+    scoped_ptr<XWalkExtensionFunctionInfo> info) {
+}
+
+void UDPSocketObject::OnLeaveMulticast(
+    scoped_ptr<XWalkExtensionFunctionInfo> info) {
+}
+
+void UDPSocketObject::OnSendString(
+    scoped_ptr<XWalkExtensionFunctionInfo> info) {
+  if (!socket_ || has_write_pending_)
+    return;
+
+  scoped_ptr<SendDOMString::Params>
+      params(SendDOMString::Params::Create(*info->arguments()));
+  if (!params) {
+    LOG(WARNING) << "Malformed parameters passed to " << info->name();
+    return;
+  }
+
+  if (params->data.size() > kBufferSize) {
+    LOG(WARNING) << "Write data bigger than the write buffer.";
+    return;
+  }
+
+  write_buffer_size_ = params->data.size();
+  memcpy(write_buffer_->data(), params->data.data(), write_buffer_size_);
+
+  if (!params->remote_address || !*params->remote_port) {
+    OnSend(net::OK);
+    return;
+  }
+
+  net::HostResolver::RequestInfo request_info(net::HostPortPair(
+      *params->remote_address, *params->remote_port));
+
+  int ret = single_resolver_->Resolve(
+      request_info,
+      net::DEFAULT_PRIORITY,
+      &addresses_,
+      base::Bind(&UDPSocketObject::OnSend,
+                 base::Unretained(this)),
+      net::BoundNetLog());
+
+  if (ret != net::ERR_IO_PENDING)
+    OnSend(ret);
+  else
+    has_write_pending_ = true;
+}
+
+void UDPSocketObject::OnRead(int status) {
+  // No data means the other side has
+  // disconnected the socket.
+  if (status == 0) {
+    setReadyState(READY_STATE_CLOSED);
+    DispatchEvent("close");
+    return;
+  }
+
+  scoped_ptr<base::Value> data(base::BinaryValue::CreateWithCopiedBuffer(
+      static_cast<char*>(read_buffer_->data()), status));
+
+  UDPMessageEvent event;
+  event.data = std::string(read_buffer_->data(), status);
+  event.remote_port = from_.port();
+  event.remote_address = from_.ToStringWithoutPort();
+
+  scoped_ptr<base::ListValue> eventData(new base::ListValue);
+  eventData->Append(event.ToValue().release());
+
+  if (!is_suspended_)
+    DispatchEvent("message", eventData.Pass());
+
+  DoRead();
+}
+
+void UDPSocketObject::OnWrite(int status) {
+  has_write_pending_ = false;
+  DispatchEvent("drain");
+}
+
+void UDPSocketObject::OnConnectionOpen(int status) {
+  if (status != net::OK) {
+    setReadyState(READY_STATE_CLOSED);
+    DispatchEvent("error");
+    return;
+  }
+
+  setReadyState(READY_STATE_OPEN);
+  DispatchEvent("open");
+}
+
+void UDPSocketObject::OnSend(int status) {
+  if (status != net::OK || addresses_.empty()) {
+    setReadyState(READY_STATE_CLOSED);
+    DispatchEvent("error");
+    return;
+  }
+
+  if (!socket_->is_connected()) {
+    // If we are waiting for reads and the socket is not connect,
+    // it means the connection was closed.
+    if (is_reading_ || socket_->Connect(addresses_[0]) != net::OK) {
+      setReadyState(READY_STATE_CLOSED);
+      DispatchEvent("error");
+      return;
+    }
+  }
+
+  int ret = socket_->SendTo(
+      write_buffer_,
+      write_buffer_size_,
+      addresses_[0],
+      base::Bind(&UDPSocketObject::OnWrite, base::Unretained(this)));
+
+  if (ret == net::ERR_IO_PENDING) {
+    has_write_pending_ = true;
+  } else if (ret == write_buffer_size_) {
+    has_write_pending_ = false;
+  } else {
+    socket_->Close();
+    setReadyState(READY_STATE_CLOSED);
+    DispatchEvent("close");
+    return;
+  }
+
+  if (!is_reading_ && socket_->is_connected())
+    DoRead();
+}
+
+}  // namespace sysapps
+}  // namespace xwalk
diff --git a/src/xwalk/sysapps/raw_socket/udp_socket_object.h b/src/xwalk/sysapps/raw_socket/udp_socket_object.h
new file mode 100644 (file)
index 0000000..ca40741
--- /dev/null
@@ -0,0 +1,63 @@
+// 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_SYSAPPS_RAW_SOCKET_UDP_SOCKET_OBJECT_H_
+#define XWALK_SYSAPPS_RAW_SOCKET_UDP_SOCKET_OBJECT_H_
+
+#include <string>
+
+#include "net/base/address_list.h"
+#include "net/base/io_buffer.h"
+#include "net/dns/single_request_host_resolver.h"
+#include "net/udp/udp_socket.h"
+#include "xwalk/sysapps/raw_socket/raw_socket_object.h"
+
+namespace xwalk {
+namespace sysapps {
+
+class UDPSocketObject : public RawSocketObject {
+ public:
+  UDPSocketObject();
+  virtual ~UDPSocketObject();
+
+ private:
+  void DoRead();
+
+  // JavaScript function handlers.
+  void OnInit(scoped_ptr<XWalkExtensionFunctionInfo> info);
+  void OnClose(scoped_ptr<XWalkExtensionFunctionInfo> info);
+  void OnSuspend(scoped_ptr<XWalkExtensionFunctionInfo> info);
+  void OnResume(scoped_ptr<XWalkExtensionFunctionInfo> info);
+  void OnJoinMulticast(scoped_ptr<XWalkExtensionFunctionInfo> info);
+  void OnLeaveMulticast(scoped_ptr<XWalkExtensionFunctionInfo> info);
+  void OnSendString(scoped_ptr<XWalkExtensionFunctionInfo> info);
+
+  // net::UDPSocket callbacks.
+  void OnRead(int status);
+  void OnWrite(int status);
+
+  // net::SingleRequestHostResolver callbacks.
+  void OnConnectionOpen(int status);
+  void OnSend(int status);
+
+  bool has_write_pending_;
+  bool is_suspended_;
+  bool is_reading_;
+
+  scoped_refptr<net::IOBuffer> read_buffer_;
+  scoped_refptr<net::IOBuffer> write_buffer_;
+  scoped_ptr<net::UDPSocket> socket_;
+
+  unsigned write_buffer_size_;
+
+  scoped_ptr<net::HostResolver> resolver_;
+  scoped_ptr<net::SingleRequestHostResolver> single_resolver_;
+  net::AddressList addresses_;
+  net::IPEndPoint from_;
+};
+
+}  // namespace sysapps
+}  // namespace xwalk
+
+#endif  // XWALK_SYSAPPS_RAW_SOCKET_UDP_SOCKET_OBJECT_H_
index cdc0aa7..848a11f 100644 (file)
@@ -66,6 +66,9 @@
         'raw_socket/tcp_socket.idl',
         'raw_socket/tcp_socket_object.cc',
         'raw_socket/tcp_socket_object.h',
+        'raw_socket/udp_socket.idl',
+        'raw_socket/udp_socket_object.cc',
+        'raw_socket/udp_socket_object.h',
       ],
       'conditions': [
         ['OS!="android"', {
index 80a210d..f64fc93 100644 (file)
@@ -16,7 +16,6 @@ import android.webkit.WebResourceResponse;
 
 import org.xwalk.core.JsPromptResult;
 import org.xwalk.core.JsResult;
-import org.xwalk.core.SslErrorHandler;
 import org.xwalk.core.XWalkContentsClient;
 import org.xwalk.core.XWalkGeolocationPermissions;
 import org.xwalk.core.XWalkHttpAuthHandler;
@@ -58,7 +57,7 @@ public class NullContentsClient extends XWalkContentsClient {
     }
 
     @Override
-    public void onReceivedSslError(SslErrorHandler handler, SslError error) {
+    public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) {
     }
 
     @Override
index b398009..f739644 100644 (file)
@@ -28,6 +28,8 @@
         '../base/base.gyp:base',
         '../base/base.gyp:base_i18n',
         '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../components/components.gyp:visitedlink_browser',
+        '../components/components.gyp:visitedlink_renderer',
         '../content/content.gyp:content',
         '../content/content.gyp:content_app_both',
         '../content/content.gyp:content_browser',
         'runtime/common/android/xwalk_render_view_messages.h',
         'runtime/common/paths_mac.h',
         'runtime/common/paths_mac.mm',
+        'runtime/common/xwalk_common_messages.cc',
+        'runtime/common/xwalk_common_messages.h',
+        'runtime/common/xwalk_common_message_generator.cc',
+        'runtime/common/xwalk_common_message_generator.h',
         'runtime/common/xwalk_content_client.cc',
         'runtime/common/xwalk_content_client.h',
         'runtime/common/xwalk_paths.cc',
         'runtime/renderer/tizen/xwalk_content_renderer_client_tizen.h',
         'runtime/renderer/xwalk_content_renderer_client.cc',
         'runtime/renderer/xwalk_content_renderer_client.h',
+        'runtime/renderer/xwalk_render_process_observer_generic.cc',
+        'runtime/renderer/xwalk_render_process_observer_generic.h',
       ],
       'includes': [
         'xwalk_jsapi.gypi',
             'xwalk_core_jar_jni',
             'xwalk_core_native_jni',
           ],
+          'sources!':[
+            'runtime/renderer/xwalk_render_process_observer_generic.cc',
+            'runtime/renderer/xwalk_render_process_observer_generic.h',
+          ],
         }],
         ['OS=="win" and win_use_allocator_shim==1', {
           'dependencies': [
index 173db0a..86d2680 100644 (file)
@@ -43,6 +43,7 @@
         'application/common/manifest_handlers/main_document_handler_unittest.cc',
         'application/common/manifest_handlers/permissions_handler_unittest.cc',
         'application/common/manifest_handlers/warp_handler_unittest.cc',
+        'application/common/manifest_handlers/widget_handler_unittest.cc',
         'application/common/manifest_handler_unittest.cc',
         'application/common/manifest_unittest.cc',
         'runtime/common/xwalk_content_client_unittest.cc',
             '../skia/skia.gyp:skia',
           ],
         }],
+        ['tizen == 1 or tizen_mobile == 1', {
+          'sources': [
+            'application/common/manifest_handlers/navigation_handler_unittest.cc',
+          ],
+        }],
       ],
     },
     {