Upstream version 11.39.244.0 03/30403/1
authorEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Mon, 17 Nov 2014 15:26:02 +0000 (15:26 +0000)
committerEurogiciel-BOT <eurogiciel.tizen@gmail.com>
Mon, 17 Nov 2014 15:26:02 +0000 (15:26 +0000)
Upstream commit-id 9605f4c84aec82d20882bdd0878d7f1a2f06e3b4

Change-Id: I745f3b6e852604e53b56a8f99c0a60e8153c6caa
Signed-off-by: Eurogiciel-BOT <eurogiciel.tizen@gmail.com>
164 files changed:
packaging/crosswalk.spec
src/build/util/LASTCHANGE
src/build/util/LASTCHANGE.blink
src/content/browser/renderer_host/media/audio_renderer_host.cc
src/content/browser/renderer_host/media/audio_renderer_host.h
src/media/audio/audio_io.h
src/media/audio/audio_output_controller.cc
src/media/audio/audio_output_controller.h
src/media/audio/audio_output_dispatcher.cc
src/media/audio/audio_output_dispatcher.h
src/media/audio/audio_output_dispatcher_impl.cc
src/media/audio/audio_output_proxy.cc
src/media/audio/audio_output_proxy.h
src/media/audio/audio_output_resampler.cc
src/media/audio/pulse/pulse.sigs
src/media/audio/pulse/pulse_output.cc
src/media/audio/pulse/pulse_output.h
src/media/audio/pulse/pulse_util.cc
src/ozone/ui/desktop_aura/desktop_window_tree_host_wayland.cc
src/third_party/WebKit/Source/bindings/core/v8/ScriptProfiler.cpp
src/third_party/WebKit/Source/bindings/core/v8/ScriptProfiler.h
src/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.cpp
src/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.h
src/third_party/WebKit/Source/core/inspector/ScriptProfile.cpp
src/third_party/WebKit/Source/core/inspector/ScriptProfile.h
src/third_party/WebKit/Source/devtools/protocol.json
src/v8/include/v8-profiler.h
src/v8/src/api.cc
src/v8/src/cpu-profiler.cc
src/v8/src/cpu-profiler.h
src/v8/src/heap-profiler.cc
src/v8/src/heap-profiler.h
src/v8/src/heap-snapshot-generator-inl.h
src/v8/src/heap-snapshot-generator.cc
src/v8/src/heap-snapshot-generator.h
src/v8/src/profile-generator-inl.h
src/v8/src/profile-generator.cc
src/v8/src/profile-generator.h
src/v8/src/xdk-allocation.cc [new file with mode: 0644]
src/v8/src/xdk-allocation.h [new file with mode: 0644]
src/v8/src/xdk-utils.cc [new file with mode: 0644]
src/v8/src/xdk-utils.h [new file with mode: 0644]
src/v8/test/cctest/test-cpu-profiler.cc
src/v8/test/cctest/test-heap-profiler.cc
src/v8/tools/gyp/v8.gyp
src/xwalk/DEPS.xwalk
src/xwalk/VERSION
src/xwalk/app/android/runtime_activity/src/org/xwalk/app/XWalkRuntimeActivityBase.java
src/xwalk/app/android/runtime_client_embedded_shell/src/org/xwalk/runtime/client/embedded/shell/XWalkRuntimeClientEmbeddedShellActivity.java
src/xwalk/app/android/runtime_client_shell/src/org/xwalk/runtime/client/shell/XWalkRuntimeClientShellActivity.java
src/xwalk/app/tools/android/customize.py
src/xwalk/app/tools/android/handle_xml.py
src/xwalk/app/tools/android/make_apk_test.py
src/xwalk/app/tools/android/test_data/extensions/adextension/AndroidManifest.xml [new file with mode: 0644]
src/xwalk/app/tools/android/test_data/extensions/adextension/adextension.js [new file with mode: 0644]
src/xwalk/app/tools/android/test_data/extensions/adextension/adextension.json [new file with mode: 0644]
src/xwalk/app/tools/android/test_data/extensions/adextension/src/com/example/extension/AdExtension.java [new file with mode: 0644]
src/xwalk/application/browser/application.cc
src/xwalk/application/browser/application.h
src/xwalk/application/browser/application_tizen.cc
src/xwalk/application/browser/application_tizen.h
src/xwalk/application/common/application_file_util.cc
src/xwalk/application/common/application_manifest_constants.cc
src/xwalk/application/common/application_manifest_constants.h
src/xwalk/application/common/constants.cc
src/xwalk/application/common/constants.h
src/xwalk/application/common/manifest_handlers/tizen_application_handler.cc
src/xwalk/application/common/manifest_handlers/tizen_setting_handler.cc
src/xwalk/application/common/manifest_handlers/tizen_setting_handler.h
src/xwalk/application/tools/tizen/xwalk_backend.cc
src/xwalk/application/tools/tizen/xwalk_backend_plugin.cc
src/xwalk/application/tools/tizen/xwalk_backend_plugin.h
src/xwalk/application/tools/tizen/xwalk_backendlib.cc
src/xwalk/application/tools/tizen/xwalk_package_installer.cc
src/xwalk/application/tools/tizen/xwalk_package_installer.h
src/xwalk/application/tools/tizen/xwalk_packageinfo_constants.h
src/xwalk/application/tools/tizen/xwalk_platform_installer.cc
src/xwalk/application/tools/tizen/xwalk_platform_installer.h
src/xwalk/application/tools/tizen/xwalk_rds_delta_parser.cc [new file with mode: 0644]
src/xwalk/application/tools/tizen/xwalk_rds_delta_parser.h [new file with mode: 0644]
src/xwalk/application/tools/tizen/xwalk_tizen_tools.gyp
src/xwalk/application/tools/tizen/xwalk_tizen_user.cc
src/xwalk/extensions/browser/xwalk_extension_process_host.cc
src/xwalk/extensions/browser/xwalk_extension_process_host.h
src/xwalk/extensions/browser/xwalk_extension_service.cc
src/xwalk/extensions/browser/xwalk_extension_service.h
src/xwalk/extensions/common/android/xwalk_extension_android.cc
src/xwalk/extensions/test/external_extension_multi_process.cc
src/xwalk/packaging/crosswalk.spec
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContent.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkContentsClientBridge.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkDevToolsServer.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkResourceClientInternal.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/XWalkViewInternal.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/extension/api/messaging/MessagingSmsManager.java
src/xwalk/runtime/android/core_internal/src/org/xwalk/core/internal/extension/api/messaging/messaging_api.js
src/xwalk/runtime/android/sample/AndroidManifest.xml
src/xwalk/runtime/android/sample/assets/create_window_1.html [new file with mode: 0644]
src/xwalk/runtime/android/sample/assets/create_window_2.html [new file with mode: 0644]
src/xwalk/runtime/android/sample/assets/favicon.html [new file with mode: 0644]
src/xwalk/runtime/android/sample/assets/icon.png [new file with mode: 0644]
src/xwalk/runtime/android/sample/assets/new_window.html [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnCreateWindowRequestedActivity.java [new file with mode: 0644]
src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnReceivedIconActivity.java [new file with mode: 0644]
src/xwalk/runtime/browser/android/renderer_host/xwalk_render_view_host_ext.cc
src/xwalk/runtime/browser/android/renderer_host/xwalk_render_view_host_ext.h
src/xwalk/runtime/browser/android/xwalk_content.cc
src/xwalk/runtime/browser/android/xwalk_content.h
src/xwalk/runtime/browser/android/xwalk_contents_client_bridge.cc
src/xwalk/runtime/browser/android/xwalk_dev_tools_server.cc
src/xwalk/runtime/browser/android/xwalk_dev_tools_server.h
src/xwalk/runtime/browser/android/xwalk_http_auth_handler.cc
src/xwalk/runtime/browser/android/xwalk_path_helper.cc
src/xwalk/runtime/browser/android/xwalk_settings.cc
src/xwalk/runtime/browser/android/xwalk_view_delegate.cc
src/xwalk/runtime/browser/blink_upstream_version.h.in [new file with mode: 0644]
src/xwalk/runtime/browser/devtools/xwalk_devtools_browsertest.cc
src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.cc
src/xwalk/runtime/browser/devtools/xwalk_devtools_delegate.h
src/xwalk/runtime/browser/runtime.cc
src/xwalk/runtime/browser/runtime.h
src/xwalk/runtime/browser/runtime_context.cc
src/xwalk/runtime/browser/runtime_defered_ui_strategy.cc [new file with mode: 0644]
src/xwalk/runtime/browser/runtime_defered_ui_strategy.h [new file with mode: 0644]
src/xwalk/runtime/browser/runtime_platform_util_android.cc
src/xwalk/runtime/browser/runtime_platform_util_tizen.cc
src/xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate.cc
src/xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate.h
src/xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate_android.cc
src/xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate_android.h
src/xwalk/runtime/browser/runtime_ui_strategy.cc [new file with mode: 0644]
src/xwalk/runtime/browser/runtime_ui_strategy.h [new file with mode: 0644]
src/xwalk/runtime/browser/tizen/render_view_context_menu_impl.cc [new file with mode: 0644]
src/xwalk/runtime/browser/tizen/render_view_context_menu_impl.h [new file with mode: 0644]
src/xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.cc [new file with mode: 0644]
src/xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.h [new file with mode: 0644]
src/xwalk/runtime/browser/ui/native_app_window_views.cc
src/xwalk/runtime/browser/ui/native_app_window_views.h
src/xwalk/runtime/browser/xwalk_app_extension_bridge.cc
src/xwalk/runtime/browser/xwalk_app_extension_bridge.h
src/xwalk/runtime/browser/xwalk_content_browser_client.cc
src/xwalk/runtime/browser/xwalk_content_browser_client.h
src/xwalk/runtime/browser/xwalk_runtime_browsertest.cc
src/xwalk/runtime/common/android/xwalk_render_view_messages.h
src/xwalk/runtime/renderer/android/xwalk_render_view_ext.cc
src/xwalk/runtime/renderer/android/xwalk_render_view_ext.h
src/xwalk/runtime/resources/devtools_discovery_page.html
src/xwalk/sysapps/raw_socket/udp_socket_object.cc
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnCreateWindowRequestedTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnReceivedIconTest.java [new file with mode: 0644]
src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/TestHelperBridge.java
src/xwalk/test/android/data/create_window_1.html [new file with mode: 0644]
src/xwalk/test/android/data/create_window_2.html [new file with mode: 0644]
src/xwalk/test/android/data/favicon.html [new file with mode: 0644]
src/xwalk/test/android/data/icon.png [new file with mode: 0644]
src/xwalk/test/android/data/new_window.html [new file with mode: 0644]
src/xwalk/test/base/in_process_browser_test.cc
src/xwalk/tizen/browser/media/browser_mediaplayer_manager.cc
src/xwalk/tizen/browser/media/murphy_resource.cc
src/xwalk/tizen/browser/media/murphy_resource.h
src/xwalk/tools/upstream_revision.py [new file with mode: 0755]
src/xwalk/xwalk.gyp
src/xwalk/xwalk_android_app.gypi
src/xwalk/xwalk_android_tests.gypi

index 7420b6f..f3c1764 100644 (file)
@@ -24,7 +24,7 @@
 %define _binary_payload w3.gzdio
 
 Name:           crosswalk
-Version:        10.39.234.0
+Version:        11.39.244.0
 Release:        0
 Summary:        Chromium-based app runtime
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -53,6 +53,7 @@ BuildRequires:  python
 BuildRequires:  python-xml
 BuildRequires:  perl
 BuildRequires:  which
+BuildRequires:  yasm
 BuildRequires:  pkgconfig(ail)
 BuildRequires:  pkgconfig(alsa)
 BuildRequires:  pkgconfig(appcore-common)
@@ -242,6 +243,7 @@ ${GYP_EXTRA_FLAGS} \
 -Duse_system_libexif=1 \
 -Duse_system_libxml=1 \
 -Duse_system_nspr=1 \
+-Duse_system_yasm=1 \
 -Dshared_process_mode=1 \
 -Denable_hidpi=1
 
index cd3eecd..4e673a8 100644 (file)
@@ -1 +1 @@
-LASTCHANGE=88fc58a654d73e2df3dffc946077486c450f3bdb
+LASTCHANGE=52d4347d95a66afe54be98677b077fce0b7fd846
index 6201a3c..fe50828 100644 (file)
@@ -1 +1 @@
-LASTCHANGE=ed2bae8ced284782cbd55f1597e02d6ee621621b
+LASTCHANGE=a6caf4f53deee46eb41c31d38dc990964615b8e5
index 8c06395..86cf8f7 100644 (file)
@@ -65,6 +65,11 @@ class AudioRendererHost::AudioEntry
   bool playing() const { return playing_; }
   void set_playing(bool playing) { playing_ = playing; }
 
+#if defined(OS_TIZEN)
+  std::string app_id() const override { return host_->app_id_; }
+  std::string app_class() const override { return host_->app_class_; }
+#endif
+
  private:
   // media::AudioOutputController::EventHandler implementation.
   virtual void OnCreated() OVERRIDE;
@@ -484,4 +489,13 @@ bool AudioRendererHost::HasActiveAudio() {
   return !base::AtomicRefCountIsZero(&num_playing_streams_);
 }
 
+#if defined(OS_TIZEN)
+void AudioRendererHost::SetMediaStreamProperties(
+    const std::string& app_id,
+    const std::string& app_class) {
+  app_id_ = app_id;
+  app_class_ = app_class;
+}
+#endif
+
 }  // namespace content
index 38317ef..cc85a6f 100644 (file)
@@ -38,6 +38,9 @@
 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
 
 #include <map>
+#if defined(OS_TIZEN)
+#include <string>
+#endif
 
 #include "base/atomic_ref_count.h"
 #include "base/gtest_prod_util.h"
@@ -89,6 +92,15 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
   // be called from any thread.
   bool HasActiveAudio();
 
+#if defined(OS_TIZEN)
+  // Sets an application ID and class properties, which are used to tag audio
+  // streams in pulseaudio/Murphy.
+  virtual void SetMediaStreamProperties(const std::string& app_id,
+                                        const std::string& app_class);
+  const std::string& app_id() const { return app_id_; }
+  const std::string& app_class() const { return app_class_; }
+#endif
+
  private:
   friend class AudioRendererHostTest;
   friend class BrowserThread;
@@ -173,6 +185,12 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
   // The number of streams in the playing state.
   base::AtomicRefCount num_playing_streams_;
 
+#if defined(OS_TIZEN)
+  // Application ID and class for the Murphy resource set.
+  std::string app_id_;
+  std::string app_class_;
+#endif
+
   DISALLOW_COPY_AND_ASSIGN(AudioRendererHost);
 };
 
index 1e1eba4..e4bb90e 100644 (file)
@@ -5,6 +5,10 @@
 #ifndef MEDIA_AUDIO_AUDIO_IO_H_
 #define MEDIA_AUDIO_AUDIO_IO_H_
 
+#if defined(OS_TIZEN)
+#include <string>
+#endif
+
 #include "base/basictypes.h"
 #include "media/audio/audio_buffers_state.h"
 #include "media/base/audio_bus.h"
@@ -99,6 +103,13 @@ class MEDIA_EXPORT AudioOutputStream {
   // Close the stream. This also generates AudioSourceCallback::OnClose().
   // After calling this method, the object should not be used anymore.
   virtual void Close() = 0;
+
+#if defined(OS_TIZEN)
+  // Sets an application ID and class properties, which are used to tag audio
+  // streams in pulseaudio/Murphy.
+  virtual void SetMediaStreamProperties(const std::string& app_id,
+                                        const std::string& app_class) {}
+#endif
 };
 
 // Models an audio sink receiving recorded audio from the audio driver.
index 45d308d..e1d015f 100644 (file)
@@ -127,6 +127,10 @@ void AudioOutputController::DoCreate(bool is_for_device_change) {
     return;
   }
 
+#if defined(OS_TIZEN)
+  stream_->SetMediaStreamProperties(handler_->app_id(), handler_->app_class());
+#endif
+
   if (!stream_->Open()) {
     DoStopCloseAndClearStream();
     state_ = kError;
index f9e1033..0fd2efd 100644 (file)
@@ -5,6 +5,10 @@
 #ifndef MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_
 #define MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_
 
+#if defined(OS_TIZEN)
+#include <string>
+#endif
+
 #include "base/atomic_ref_count.h"
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
@@ -69,6 +73,11 @@ class MEDIA_EXPORT AudioOutputController
     virtual void OnError() = 0;
     virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate) = 0;
 
+#if defined(OS_TIZEN)
+    virtual std::string app_id() const = 0;
+    virtual std::string app_class() const = 0;
+#endif
+
    protected:
     virtual ~EventHandler() {}
   };
index 7f3dd10..37a6410 100644 (file)
@@ -25,4 +25,13 @@ AudioOutputDispatcher::~AudioOutputDispatcher() {
   DCHECK(task_runner_->BelongsToCurrentThread());
 }
 
+#if defined(OS_TIZEN)
+void AudioOutputDispatcher::SetMediaStreamProperties(
+    const std::string& app_id,
+    const std::string& app_class) {
+  app_id_ = app_id;
+  app_class_ = app_class;
+}
+#endif
+
 }  // namespace media
index 079cba0..115b89f 100644 (file)
 #ifndef MEDIA_AUDIO_AUDIO_OUTPUT_DISPATCHER_H_
 #define MEDIA_AUDIO_AUDIO_OUTPUT_DISPATCHER_H_
 
+#if defined(OS_TIZEN)
+#include <string>
+#endif
+
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/timer/timer.h"
@@ -67,6 +71,11 @@ class MEDIA_EXPORT AudioOutputDispatcher
 
   const std::string& device_id() const { return device_id_; }
 
+#if defined(OS_TIZEN)
+  virtual void SetMediaStreamProperties(const std::string& app_id,
+                                        const std::string& app_class);
+#endif
+
  protected:
   friend class base::RefCountedThreadSafe<AudioOutputDispatcher>;
   virtual ~AudioOutputDispatcher();
@@ -78,6 +87,11 @@ class MEDIA_EXPORT AudioOutputDispatcher
   const AudioParameters params_;
   std::string device_id_;
 
+#if defined(OS_TIZEN)
+  std::string app_id_;
+  std::string app_class_;
+#endif
+
  private:
   DISALLOW_COPY_AND_ASSIGN(AudioOutputDispatcher);
 };
index 0cb3db8..f44ae30 100644 (file)
@@ -137,6 +137,10 @@ bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
   if (!stream)
     return false;
 
+#if defined(OS_TIZEN)
+  stream->SetMediaStreamProperties(app_id_, app_class_);
+#endif
+
   if (!stream->Open()) {
     stream->Close();
     return false;
index a69cbc9..10d8751 100644 (file)
@@ -90,4 +90,11 @@ void AudioOutputProxy::Close() {
   delete this;
 }
 
+#if defined(OS_TIZEN)
+void AudioOutputProxy::SetMediaStreamProperties(const std::string& app_id,
+                                                const std::string& app_class) {
+  dispatcher_->SetMediaStreamProperties(app_id, app_class);
+}
+#endif
+
 }  // namespace media
index 86dab51..4f5c6e3 100644 (file)
@@ -5,6 +5,10 @@
 #ifndef MEDIA_AUDIO_AUDIO_OUTPUT_PROXY_H_
 #define MEDIA_AUDIO_AUDIO_OUTPUT_PROXY_H_
 
+#if defined(OS_TIZEN)
+#include <string>
+#endif
+
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
@@ -39,6 +43,11 @@ class MEDIA_EXPORT AudioOutputProxy
   virtual void GetVolume(double* volume) OVERRIDE;
   virtual void Close() OVERRIDE;
 
+#if defined(OS_TIZEN)
+  void SetMediaStreamProperties(const std::string& app_id,
+                                const std::string& app_class) override;
+#endif
+
  private:
   enum State {
     kCreated,
index 5926996..da28002 100644 (file)
@@ -178,6 +178,10 @@ void AudioOutputResampler::Initialize() {
 bool AudioOutputResampler::OpenStream() {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
+#if defined(OS_TIZEN)
+  dispatcher_->SetMediaStreamProperties(app_id_, app_class_);
+#endif
+
   if (dispatcher_->OpenStream()) {
     // Only record the UMA statistic if we didn't fallback during construction
     // and only for the first stream we open.
@@ -246,6 +250,10 @@ bool AudioOutputResampler::StartStream(
     resampler_callback = it->second;
   }
 
+#if defined(OS_TIZEN)
+  dispatcher_->SetMediaStreamProperties(app_id_, app_class_);
+#endif
+
   resampler_callback->Start(callback);
   bool result = dispatcher_->StartStream(resampler_callback, stream_proxy);
   if (!result)
index 8d2dab7..03d9aa8 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 set the audio stream role.
+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 e0a0b42..4f556c1 100644 (file)
@@ -234,4 +234,13 @@ void PulseAudioOutputStream::GetVolume(double* volume) {
   *volume = volume_;
 }
 
+#if defined(OS_TIZEN)
+void PulseAudioOutputStream::SetMediaStreamProperties(
+    const std::string& app_id,
+    const std::string& app_class) {
+  app_id_ = app_id;
+  app_class_ = app_class;
+}
+#endif
+
 }  // namespace media
index e1c0045..a0be5a6 100644 (file)
@@ -51,6 +51,13 @@ class PulseAudioOutputStream : public AudioOutputStream {
   virtual void SetVolume(double volume) OVERRIDE;
   virtual void GetVolume(double* volume) OVERRIDE;
 
+#if defined(OS_TIZEN)
+  void SetMediaStreamProperties(const std::string& app_id,
+                                const std::string& app_class) override;
+  const std::string& app_id() const {return app_id_;}
+  const std::string& app_class() const {return app_class_;}
+#endif
+
  private:
   // Called by PulseAudio when |pa_stream_| change state.  If an unexpected
   // failure state change happens and |source_callback_| is set
@@ -91,6 +98,12 @@ class PulseAudioOutputStream : public AudioOutputStream {
   // Container for retrieving data from AudioSourceCallback::OnMoreData().
   scoped_ptr<AudioBus> audio_bus_;
 
+#if defined(OS_TIZEN)
+  // Application ID and class for the pulseaudio streams.
+  std::string app_id_;
+  std::string app_class_;
+#endif
+
   base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(PulseAudioOutputStream);
index c06195e..020ad3d 100644 (file)
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#if defined(OS_TIZEN)
+#include "media/audio/pulse/pulse_output.h"
+#endif
+
 #include "media/audio/pulse/pulse_util.h"
 
 #include "base/logging.h"
@@ -259,7 +263,20 @@ bool CreateOutputStream(pa_threaded_mainloop** mainloop,
     // than the default channel map (NULL).
     map = &source_channel_map;
   }
+
+#if defined(OS_TIZEN)
+  PulseAudioOutputStream* data =
+      static_cast<PulseAudioOutputStream*>(user_data);
+  pa_proplist* proplist = pa_proplist_new();
+  pa_proplist_sets(proplist, "resource.set.appid", data->app_id().c_str());
+  pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, data->app_class().c_str());
+  *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 656ac7d..c00e21a 100644 (file)
@@ -464,6 +464,8 @@ void DesktopWindowTreeHostWayland::Minimize() {
 }
 
 void DesktopWindowTreeHostWayland::Restore() {
+  g_delegate_ozone_wayland_->SetActiveWindow(this);
+
   if (state_ & Normal)
     return;
 
index be022fd..810cd81 100644 (file)
@@ -307,4 +307,58 @@ void ScriptProfiler::setIdle(bool isIdle)
         profiler->SetIdle(isIdle);
 }
 
+namespace {
+
+class HeapXDKStream : public v8::OutputStream {
+public:
+    HeapXDKStream(ScriptProfiler::OutputStream* stream) : m_stream(stream) { }
+    virtual void EndOfStream() OVERRIDE { }
+
+    virtual WriteResult WriteAsciiChunk(char* data, int size) OVERRIDE
+    {
+        ASSERT(false);
+        return kAbort;
+    }
+
+    virtual WriteResult WriteHeapXDKChunk(const char* symbols, int symbolsSize,
+                                          const char* frames, int framesSize,
+                                          const char* types, int typesSize,
+                                          const char* chunks, int chunksSize,
+                                          const char* retentions, 
+                                          int retentionSize) OVERRIDE
+    {
+        m_stream->write(symbols, symbolsSize, frames, framesSize,
+                        types, typesSize, chunks, chunksSize,
+                        retentions, retentionSize);
+        return kContinue;
+    }
+
+private:
+    ScriptProfiler::OutputStream* m_stream;
+};
+
+}
+
+void ScriptProfiler::requestHeapXDKUpdate(ScriptProfiler::OutputStream* stream)
+{
+    HeapXDKStream heapXDKStream(stream);
+    v8::Isolate::GetCurrent()->GetHeapProfiler()->GetHeapXDKStats(
+            &heapXDKStream);
+}
+
+void ScriptProfiler::startTrackingHeapObjectsXDK(int stackDepth,
+                                                 bool retentions)
+{
+    v8::Isolate::GetCurrent()->GetHeapProfiler()->StartTrackingHeapObjectsXDK(
+            stackDepth, retentions);
+}
+
+PassRefPtr<HeapProfileXDK> ScriptProfiler::stopTrackingHeapObjectsXDK()
+{
+    return HeapProfileXDK::create(
+            v8::Isolate::GetCurrent()
+                    ->GetHeapProfiler()->StopTrackingHeapObjectsXDK());
+}
+
+
 } // namespace blink
index 826efdd..b68e448 100644 (file)
@@ -62,6 +62,11 @@ public:
     public:
         virtual ~OutputStream() { }
         virtual void write(const uint32_t* chunk, const int size) = 0;
+        virtual void write(const char* symbols, int symbolsSize,
+                           const char* frames, int framesSize,
+                           const char* types, int typesSize,
+                           const char* chunks, int chunksSize,
+                           const char* retentions, int retentionsSize) { };
     };
 
     static void collectGarbage();
@@ -75,6 +80,9 @@ public:
     static void startTrackingHeapObjects(bool trackAllocations);
     static void stopTrackingHeapObjects();
     static unsigned requestHeapStatsUpdate(OutputStream*);
+    static void startTrackingHeapObjectsXDK(int stackDepth, bool retentions);
+    static PassRefPtr<HeapProfileXDK> stopTrackingHeapObjectsXDK();
+    static void requestHeapXDKUpdate(OutputStream*);
     static void initialize();
     static void visitNodeWrappers(WrappedNodeVisitor*);
     static HashMap<String, double>* currentProfileNameIdleTimeMap();
index ed6b607..36ea17d 100644 (file)
@@ -61,6 +61,20 @@ private:
     Timer<HeapStatsUpdateTask> m_timer;
 };
 
+
+class InspectorHeapProfilerAgent::HeapXDKUpdateTask FINAL : public NoBaseWillBeGarbageCollectedFinalized<InspectorHeapProfilerAgent::HeapXDKUpdateTask> {
+public:
+    HeapXDKUpdateTask(InspectorHeapProfilerAgent*);
+    void startTimer(float sav);
+    void resetTimer() { m_timer.stop(); }
+    void onTimer(Timer<HeapXDKUpdateTask>*);
+
+private:
+    InspectorHeapProfilerAgent* m_heapProfilerAgent;
+    Timer<HeapXDKUpdateTask> m_timer;
+};
+
+
 PassOwnPtrWillBeRawPtr<InspectorHeapProfilerAgent> InspectorHeapProfilerAgent::create(InjectedScriptManager* injectedScriptManager)
 {
     return adoptPtrWillBeNoop(new InspectorHeapProfilerAgent(injectedScriptManager));
@@ -325,5 +339,118 @@ void InspectorHeapProfilerAgent::trace(Visitor* visitor)
     InspectorBaseAgent::trace(visitor);
 }
 
+static PassRefPtr<TypeBuilder::HeapProfiler::HeapEventXDK> createHeapProfileXDK(const HeapProfileXDK& heapProfileXDK)
+{
+    RefPtr<TypeBuilder::HeapProfiler::HeapEventXDK> profile = TypeBuilder::HeapProfiler::HeapEventXDK::create()
+        .setDuration(heapProfileXDK.getDuration())
+        .setSymbols(heapProfileXDK.getSymbols())
+        .setFrames(heapProfileXDK.getFrames())
+        .setTypes(heapProfileXDK.getTypes())
+        .setChunks(heapProfileXDK.getChunks())
+        .setRetentions(heapProfileXDK.getRetentions());
+    return profile.release();
+}
+
+InspectorHeapProfilerAgent::HeapXDKUpdateTask::HeapXDKUpdateTask(InspectorHeapProfilerAgent* heapProfilerAgent)
+    : m_heapProfilerAgent(heapProfilerAgent)
+    , m_timer(this, &HeapXDKUpdateTask::onTimer)
+{
+}
+
+void InspectorHeapProfilerAgent::HeapXDKUpdateTask::onTimer(Timer<HeapXDKUpdateTask>*)
+{
+    // The timer is stopped on m_heapProfilerAgent destruction,
+    // so this method will never be called after m_heapProfilerAgent has been destroyed.
+    m_heapProfilerAgent->requestHeapXDKUpdate();
+}
+
+void InspectorHeapProfilerAgent::HeapXDKUpdateTask::startTimer(float sav)
+{
+    ASSERT(!m_timer.isActive());
+    m_timer.startRepeating(sav, FROM_HERE);
+}
+
+void InspectorHeapProfilerAgent::startTrackingHeapXDK(ErrorString*, 
+                                                      const int* stack_depth,
+                                                      const int* sav,
+                                                      const bool* retentions)
+{
+    m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true);
+
+    // inline of startTrackingHeapObjectsInternal(allocationTrackingEnabled);
+    if (m_heapXDKUpdateTask)
+        return;
+    int stackDepth = 8;
+    if (stack_depth) {
+      stackDepth = *stack_depth;
+    }
+    float sav_timer = 1;
+    if (sav) {
+      sav_timer = (float)*sav / 1000.;
+    }
+    bool needRetentions = retentions && *retentions;
+    ScriptProfiler::startTrackingHeapObjectsXDK(stackDepth, needRetentions );
+    m_heapXDKUpdateTask = adoptPtr(new HeapXDKUpdateTask(this));
+    m_heapXDKUpdateTask->startTimer(sav_timer);
+}
+
+class InspectorHeapProfilerAgent::HeapXDKStream FINAL : public ScriptProfiler::OutputStream {
+public:
+    HeapXDKStream(InspectorHeapProfilerAgent* heapProfilerAgent)
+        : m_heapProfilerAgent(heapProfilerAgent)
+    {
+    }
+
+    virtual void write(const uint32_t* chunk, const int size){}
+    virtual void write(const char* symbols, int symbolsSize,
+                       const char* frames, int framesSize,
+                       const char* types, int typesSize,
+                       const char* chunks, int chunksSize,
+                       const char* retentions, int retentionsSize) OVERRIDE
+    {
+        m_heapProfilerAgent->pushHeapXDKUpdate(symbols, symbolsSize, frames, framesSize, 
+                                               types, typesSize, chunks, chunksSize,
+                                               retentions, retentionsSize);
+    }
+private:
+    InspectorHeapProfilerAgent* m_heapProfilerAgent;
+};
+
+void InspectorHeapProfilerAgent::requestHeapXDKUpdate()
+{
+    if (!m_frontend)
+        return;
+    HeapXDKStream stream(this);
+    ScriptProfiler::requestHeapXDKUpdate(&stream);
+}
+
+void InspectorHeapProfilerAgent::stopTrackingHeapXDK(ErrorString* error, RefPtr<TypeBuilder::HeapProfiler::HeapEventXDK>& profile)
+{
+    if (!m_heapXDKUpdateTask) {
+        *error = "Heap object tracking is not started.";
+        return;
+    }
+
+    RefPtr<HeapProfileXDK> heapProfileXDK = ScriptProfiler::stopTrackingHeapObjectsXDK();
+    profile = createHeapProfileXDK(*heapProfileXDK);
+    
+    m_heapXDKUpdateTask->resetTimer();
+    m_heapXDKUpdateTask.clear();
+    m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, false);
+
+}
+void InspectorHeapProfilerAgent::pushHeapXDKUpdate( const char* symbols, int symbolsSize,
+                                        const char* frames, int framesSize,
+                                        const char* types, int typesSize,
+                                        const char* chunks, int chunksSize,
+                                        const char* retentions, int retentionsSize)
+{
+    if (!m_frontend)
+        return;
+    m_frontend->heapXDKUpdate(String(symbols, symbolsSize), String(frames, framesSize), 
+                              String(types, typesSize), String(chunks, chunksSize), 
+                              String(retentions, retentionsSize));
+}
+
 } // namespace blink
 
index ac3ce51..03be422 100644 (file)
@@ -6,7 +6,8 @@
  * met:
  *
  *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of co
+ * nditions and the following disclaimer.
  *     * Redistributions in binary form must reproduce the above
  * copyright notice, this list of conditions and the following disclaimer
  * in the documentation and/or other materials provided with the
@@ -62,6 +63,8 @@ public:
     virtual void disable(ErrorString*) OVERRIDE;
     virtual void startTrackingHeapObjects(ErrorString*, const bool* trackAllocations) OVERRIDE;
     virtual void stopTrackingHeapObjects(ErrorString*, const bool* reportProgress) OVERRIDE;
+    virtual void startTrackingHeapXDK(ErrorString*, const int* stack_depth, const int* sav, const bool* retentions) OVERRIDE;
+    virtual void stopTrackingHeapXDK(ErrorString*, RefPtr<TypeBuilder::HeapProfiler::HeapEventXDK>&) OVERRIDE;
 
     virtual void setFrontend(InspectorFrontend*) OVERRIDE;
     virtual void clearFrontend() OVERRIDE;
@@ -76,11 +79,21 @@ private:
     class HeapStatsStream;
     class HeapStatsUpdateTask;
 
+    class HeapXDKStream;
+    class HeapXDKUpdateTask;
+
     explicit InspectorHeapProfilerAgent(InjectedScriptManager*);
 
     void requestHeapStatsUpdate();
     void pushHeapStatsUpdate(const uint32_t* const data, const int size);
 
+    void requestHeapXDKUpdate();
+    void pushHeapXDKUpdate(const char* symbols, int symbolsSize,
+                           const char* frames, int framesSize,
+                           const char* types, int typesSize,
+                           const char* chunks, int chunksSize,
+                           const char* retentions, int retentionsSize);
+
     void startTrackingHeapObjectsInternal(bool trackAllocations);
     void stopTrackingHeapObjectsInternal();
 
@@ -88,6 +101,7 @@ private:
     InspectorFrontend::HeapProfiler* m_frontend;
     unsigned m_nextUserInitiatedHeapSnapshotNumber;
     OwnPtrWillBeMember<HeapStatsUpdateTask> m_heapStatsUpdateTask;
+    OwnPtrWillBeMember<HeapXDKUpdateTask> m_heapXDKUpdateTask;
 };
 
 } // namespace blink
index e835b01..f352976 100644 (file)
@@ -64,6 +64,26 @@ double ScriptProfile::endTime() const
     return static_cast<double>(m_profile->GetEndTime()) / 1000000;
 }
 
+static RefPtr<TypeBuilder::Array<TypeBuilder::Profiler::LineTick> > buildInspectorObjectForLineTicks(const v8::CpuProfileNode* node)
+{
+    RefPtr<TypeBuilder::Array<TypeBuilder::Profiler::LineTick> > array = TypeBuilder::Array<TypeBuilder::Profiler::LineTick>::create();
+    unsigned int lineCount = node->GetHitLineCount();
+    if (lineCount) {
+        Vector<v8::CpuProfileNode::LineTick> entries(lineCount);
+        bool res = node->GetLineTicks(&entries[0], lineCount);
+        if (res) {
+            for (unsigned int i = 0; i < lineCount; i++) {
+                RefPtr<TypeBuilder::Profiler::LineTick> line = TypeBuilder::Profiler::LineTick::create()
+                    .setLine(entries[i].line)
+                    .setTicks(entries[i].hit_count);
+                array->addItem(line);
+                line.release();
+            }
+        }
+    }
+    return array;
+}
+
 static PassRefPtr<TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectFor(const v8::CpuProfileNode* node)
 {
     v8::HandleScope handleScope(v8::Isolate::GetCurrent());
@@ -75,6 +95,8 @@ static PassRefPtr<TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectFor
         children->addItem(buildInspectorObjectFor(child));
     }
 
+    RefPtr<TypeBuilder::Array<TypeBuilder::Profiler::LineTick> > lineTicks = buildInspectorObjectForLineTicks(node);
+
     RefPtr<TypeBuilder::Profiler::CPUProfileNode> result = TypeBuilder::Profiler::CPUProfileNode::create()
         .setFunctionName(toCoreString(node->GetFunctionName()))
         .setScriptId(String::number(node->GetScriptId()))
@@ -84,6 +106,7 @@ static PassRefPtr<TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectFor
         .setHitCount(node->GetHitCount())
         .setCallUID(node->GetCallUid())
         .setChildren(children.release())
+        .setLineTicks(lineTicks.release())
         .setDeoptReason(node->GetBailoutReason())
         .setId(node->GetNodeId());
     return result.release();
@@ -112,4 +135,34 @@ PassRefPtr<TypeBuilder::Array<double> > ScriptProfile::buildInspectorObjectForTi
     return array.release();
 }
 
+String HeapProfileXDK::getSymbols() const
+{
+    return String(m_event->getSymbols()); 
+}
+
+String HeapProfileXDK::getFrames() const
+{
+    return String(m_event->getFrames()); 
+}
+
+String HeapProfileXDK::getTypes() const
+{
+    return String(m_event->getTypes()); 
+}
+
+String HeapProfileXDK::getChunks() const
+{
+    return String(m_event->getChunks()); 
+}
+
+int HeapProfileXDK::getDuration() const
+{
+    return (int)m_event->getDuration(); 
+}
+
+String HeapProfileXDK::getRetentions() const
+{
+    return String(m_event->getRetentions());
+}
+
 } // namespace blink
index ad8e652..af522ce 100644 (file)
@@ -69,6 +69,30 @@ private:
     double m_idleTime;
 };
 
+class HeapProfileXDK FINAL : public RefCountedWillBeGarbageCollectedFinalized<HeapProfileXDK> {
+public:
+    static PassRefPtrWillBeRawPtr<HeapProfileXDK> create(v8::HeapEventXDK* event)
+    {
+        return adoptRefWillBeNoop(new HeapProfileXDK(event));
+    }
+
+    String getSymbols() const;
+    String getFrames() const;
+    String getTypes() const;
+    String getChunks() const;
+    String getRetentions() const;
+    int getDuration() const;
+
+private:
+    HeapProfileXDK(v8::HeapEventXDK* event)
+        : m_event(event)
+    {
+    }
+
+    v8::HeapEventXDK* m_event;
+
+};
+
 } // namespace blink
 
 #endif // ScriptProfile_h
index 12246b8..8b6a9a4 100644 (file)
                     { "name": "callUID", "type": "number", "description": "Call UID." },
                     { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Child nodes." },
                     { "name": "deoptReason", "type": "string", "description": "The reason of being not optimized. The function may be deoptimized or marked as don't optimize."},
-                    { "name": "id", "type": "integer", "description": "Unique id of the node." }
+                    { "name": "id", "type": "integer", "description": "Unique id of the node." },
+                    { "name": "lineTicks", "type": "array", "items": { "$ref": "LineTick" }, "description": "A set of source line ticks." }
                 ]
             },
             {
                     { "name": "samples", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Ids of samples top nodes." },
                     { "name": "timestamps", "optional": true, "type": "array", "items": { "type": "number" }, "description": "Timestamps of the samples in microseconds." }
                 ]
-            }
+            },
+            {\r
+                "id": "LineTick",\r
+                "type": "object",\r
+                "description": "Specifies a number of samples attributed to a certain source line.",\r
+                "properties": [\r
+                    { "name": "line", "type": "integer", "description": "Source line number." },\r
+                    { "name": "ticks", "type": "integer", "description": "Number of samples attributed to a source line number." }\r
+                ]\r
+            }\r
         ],
         "commands": [
             {
                 "id": "HeapSnapshotObjectId",
                 "type": "string",
                 "description": "Heap snapshot object id."
+            },
+            {
+                "id": "HeapEventXDK",
+                "type": "object",
+                "description": "",
+                "properties": [
+                    { "name": "duration", "type": "integer" },
+                    { "name": "symbols", "type": "string" },
+                    { "name": "frames", "type": "string" },
+                    { "name": "types", "type": "string" },
+                    { "name": "chunks", "type": "string" },
+                   { "name": "retentions", "type": "string" }
+                ]
             }
         ],
         "commands": [
 
             },
             {
+                "name": "startTrackingHeapXDK",
+                "parameters": [
+                    { "name": "stack_depth", "type": "integer", "optional": true },
+                    { "name": "sav", "type": "integer", "optional": true },
+                    { "name": "retentions", "type": "boolean", "optional": true }
+                ]
+            },
+            {
+                "name": "stopTrackingHeapXDK",
+                "returns": [
+                    { "name": "profileXDK", "$ref": "HeapEventXDK", "description": "Recorded profile." }
+                ]
+            },
+            {
                 "name": "takeHeapSnapshot",
                 "parameters": [
                     { "name": "reportProgress", "type": "boolean", "optional": true, "description": "If true 'reportHeapSnapshotProgress' events will be generated while snapshot is being taken." }
                 "parameters": [
                     { "name": "statsUpdate", "type": "array", "items": { "type": "integer" }, "description": "An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment."}
                 ]
-            }
+            },
+           {
+                "name": "heapXDKUpdate",
+                "parameters": [
+                   { "name": "symbols", "type": "string" },
+                   { "name": "frames", "type": "string" },
+                   { "name": "types", "type": "string" },
+                   { "name": "chunks", "type": "string" },
+                   { "name": "retentions", "type": "string" }
+                ]
+           }
         ]
     },
     {
index d021520..b1ae6eb 100644 (file)
@@ -143,6 +143,19 @@ class V8_EXPORT CpuProfile {
 
 
 /**
+ * HeapEventXDK contains the latest chunk of heap info
+ */
+class V8_EXPORT HeapEventXDK {
+ public:
+  const char* getSymbols();
+  const char* getFrames();
+  const char* getTypes();
+  const char* getChunks();
+  const char* getRetentions();
+  unsigned int getDuration();
+};
+
+/**
  * Interface for controlling CPU profiling. Instance of the
  * profiler can be retrieved using v8::Isolate::GetCpuProfiler.
  */
@@ -314,6 +327,19 @@ class V8_EXPORT OutputStream {  // NOLINT
   virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) {
     return kAbort;
   }
+
+
+  /**
+   * Writes XDK object
+   */
+  virtual WriteResult WriteHeapXDKChunk(const char* symbols, int symbolsSize,
+                                        const char* frames, int framesSize,
+                                        const char* types, int typesSize,
+                                        const char* chunks, int chunksSize,
+                                        const char* retentions,
+                                        int retentionSize) {
+    return kAbort;
+  }
 };
 
 
@@ -530,6 +556,14 @@ class V8_EXPORT HeapProfiler {
    */
   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
 
+  void StartTrackingHeapObjectsXDK(int stackDepth, bool retentions,
+      bool strict_collection = false);
+  /**
+   * @author amalyshe
+   */
+  void GetHeapXDKStats(OutputStream* stream);
+  HeapEventXDK* StopTrackingHeapObjectsXDK();
+
  private:
   HeapProfiler();
   ~HeapProfiler();
index 2546456..7e612cd 100644 (file)
@@ -47,7 +47,7 @@
 #include "src/v8threads.h"
 #include "src/version.h"
 #include "src/vm-state-inl.h"
-
+#include "src/xdk-allocation.h"
 
 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
 
@@ -7316,6 +7316,47 @@ Handle<String> HeapSnapshot::GetTitle() const {
 }
 
 
+const char* HeapEventXDK::getSymbols() {
+  const i::HeapEventXDK* eventXDK =
+    reinterpret_cast<const i::HeapEventXDK*>(this);
+  return eventXDK->symbols();
+}
+
+
+const char* HeapEventXDK::getFrames() {
+  const i::HeapEventXDK* eventXDK =
+    reinterpret_cast<const i::HeapEventXDK*>(this);
+  return eventXDK->frames();
+}
+
+
+const char* HeapEventXDK::getTypes() {
+  const i::HeapEventXDK* eventXDK =
+    reinterpret_cast<const i::HeapEventXDK*>(this);
+  return eventXDK->types();
+}
+
+
+const char* HeapEventXDK::getChunks() {
+  const i::HeapEventXDK* eventXDK =
+      reinterpret_cast<const i::HeapEventXDK*>(this);
+  return eventXDK->chunks();
+}
+
+
+const char* HeapEventXDK::getRetentions() {
+  const i::HeapEventXDK* eventXDK =
+    reinterpret_cast<const i::HeapEventXDK*>(this);
+  return eventXDK->retentions();
+}
+
+
+unsigned int HeapEventXDK::getDuration() {
+  const i::HeapEventXDK* eventXDK =
+    reinterpret_cast<const i::HeapEventXDK*>(this);
+  return eventXDK->duration();
+}
+
 const HeapGraphNode* HeapSnapshot::GetRoot() const {
   return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
 }
@@ -7412,6 +7453,24 @@ SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
 }
 
 
+void HeapProfiler::GetHeapXDKStats(OutputStream* stream) {
+  reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsXDKStats(stream);
+}
+
+
+void HeapProfiler::StartTrackingHeapObjectsXDK(int stackDepth,
+    bool retentions, bool strict_collection) {
+  reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTrackingXDK(
+      stackDepth, retentions, strict_collection);
+}
+
+
+HeapEventXDK* HeapProfiler::StopTrackingHeapObjectsXDK() {
+  return reinterpret_cast<HeapEventXDK*>(
+    reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTrackingXDK());
+}
+
+
 void HeapProfiler::DeleteAllHeapSnapshots() {
   reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
 }
index 115324c..2d611b4 100644 (file)
@@ -20,17 +20,16 @@ namespace internal {
 static const int kProfilerStackSize = 64 * KB;
 
 
-ProfilerEventsProcessor::ProfilerEventsProcessor(
-    ProfileGenerator* generator,
-    Sampler* sampler,
-    base::TimeDelta period)
+ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator,
+                                                 Sampler* sampler,
+                                                 base::TimeDelta period)
     : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
       generator_(generator),
       sampler_(sampler),
-      running_(true),
+      running_(1),
       period_(period),
-      last_code_event_id_(0), last_processed_code_event_id_(0) {
-}
+      last_code_event_id_(0),
+      last_processed_code_event_id_(0) {}
 
 
 void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) {
@@ -55,8 +54,7 @@ void ProfilerEventsProcessor::AddCurrentStack(Isolate* isolate) {
 
 
 void ProfilerEventsProcessor::StopSynchronously() {
-  if (!running_) return;
-  running_ = false;
+  if (!base::NoBarrier_AtomicExchange(&running_, 0)) return;
   Join();
 }
 
@@ -107,7 +105,7 @@ ProfilerEventsProcessor::SampleProcessingResult
 
 
 void ProfilerEventsProcessor::Run() {
-  while (running_) {
+  while (!!base::NoBarrier_Load(&running_)) {
     base::ElapsedTimer timer;
     timer.Start();
     // Keep processing existing events until we need to do next sample.
@@ -201,7 +199,15 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
   CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
   CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
   rec->start = code->address();
-  rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+  rec->entry = profiles_->NewCodeEntry(
+      tag,
+      profiles_->GetFunctionName(name),
+      CodeEntry::kEmptyNamePrefix,
+      CodeEntry::kEmptyResourceName,
+      CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo,
+      NULL,
+      code->instruction_start());
   rec->size = code->ExecutableSize();
   rec->shared = NULL;
   processor_->Enqueue(evt_rec);
@@ -215,7 +221,15 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
   CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
   CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
   rec->start = code->address();
-  rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+  rec->entry = profiles_->NewCodeEntry(
+      tag,
+      profiles_->GetFunctionName(name),
+      CodeEntry::kEmptyNamePrefix,
+      CodeEntry::kEmptyResourceName,
+      CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo,
+      NULL,
+      code->instruction_start());
   rec->size = code->ExecutableSize();
   rec->shared = NULL;
   processor_->Enqueue(evt_rec);
@@ -231,7 +245,11 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
   rec->start = code->address();
   rec->entry = profiles_->NewCodeEntry(
       tag, profiles_->GetFunctionName(shared->DebugName()),
-      CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name));
+      CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name),
+      CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo,
+      NULL,
+      code->instruction_start());
   if (info) {
     rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
   }
@@ -256,11 +274,9 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
   CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
   CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
   rec->start = code->address();
-  Script* script = NULL;
+  Script* script = Script::cast(shared->script());
   JITLineInfoTable* line_table = NULL;
-  if (shared->script()->IsScript()) {
-    DCHECK(Script::cast(shared->script()));
-    script = Script::cast(shared->script());
+  if (script) {
     line_table = new JITLineInfoTable();
     for (RelocIterator it(code); !it.done(); it.next()) {
       RelocInfo::Mode mode = it.rinfo()->rmode();
@@ -277,17 +293,15 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
   rec->entry = profiles_->NewCodeEntry(
       tag, profiles_->GetFunctionName(shared->DebugName()),
       CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), line,
-      column, line_table);
+      column, line_table, code->instruction_start());
   if (info) {
     rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
   }
-  if (script) {
-    rec->entry->set_script_id(script->id()->value());
-  }
-  rec->entry->set_bailout_reason(
-      GetBailoutReason(shared->DisableOptimizationReason()));
+  rec->entry->set_script_id(script->id()->value());
   rec->size = code->ExecutableSize();
   rec->shared = shared->address();
+  rec->entry->set_bailout_reason(
+      GetBailoutReason(shared->DisableOptimizationReason()));
   processor_->Enqueue(evt_rec);
 }
 
@@ -302,7 +316,12 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
   rec->entry = profiles_->NewCodeEntry(
       tag,
       profiles_->GetName(args_count),
-      "args_count: ");
+      "args_count: ",
+      CodeEntry::kEmptyResourceName,
+      CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo,
+      NULL,
+      code->instruction_start());
   rec->size = code->ExecutableSize();
   rec->shared = NULL;
   processor_->Enqueue(evt_rec);
@@ -364,7 +383,12 @@ void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
   rec->entry = profiles_->NewCodeEntry(
       Logger::REG_EXP_TAG,
       profiles_->GetName(source),
-      "RegExp: ");
+      "RegExp: ",
+      CodeEntry::kEmptyResourceName,
+      CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo,
+      NULL,
+      code->instruction_start());
   rec->size = code->ExecutableSize();
   processor_->Enqueue(evt_rec);
 }
index c1e75a1..4dc5643 100644 (file)
@@ -132,7 +132,7 @@ class ProfilerEventsProcessor : public base::Thread {
   // Thread control.
   virtual void Run();
   void StopSynchronously();
-  INLINE(bool running()) { return running_; }
+  INLINE(bool running()) { return !!base::NoBarrier_Load(&running_); }
   void Enqueue(const CodeEventsContainer& event);
 
   // Puts current stack into tick sample events buffer.
@@ -163,7 +163,7 @@ class ProfilerEventsProcessor : public base::Thread {
 
   ProfileGenerator* generator_;
   Sampler* sampler_;
-  bool running_;
+  base::Atomic32 running_;
   // Sampling period in microseconds.
   const base::TimeDelta period_;
   UnboundQueue<CodeEventsContainer> events_buffer_;
index d86ce5e..eec5fd1 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "src/allocation-tracker.h"
 #include "src/heap-snapshot-generator-inl.h"
+#include "src/xdk-allocation.h"
 
 namespace v8 {
 namespace internal {
@@ -68,7 +69,7 @@ HeapSnapshot* HeapProfiler::TakeSnapshot(
     v8::HeapProfiler::ObjectNameResolver* resolver) {
   HeapSnapshot* result = new HeapSnapshot(this, name, next_snapshot_uid_++);
   {
-    HeapSnapshotGenerator generator(result, control, resolver, heap());
+    HeapSnapshotGenerator generator(this, result, control, resolver, heap());
     if (!generator.GenerateSnapshot()) {
       delete result;
       result = NULL;
@@ -115,6 +116,46 @@ void HeapProfiler::StopHeapObjectsTracking() {
 }
 
 
+void HeapProfiler::StartHeapObjectsTrackingXDK(int stackDepth,
+    bool retentions, bool strict_collection) {
+  ids_->UpdateHeapObjectsMap();
+  is_tracking_object_moves_ = true;
+  DCHECK(!is_tracking_allocations());
+  allocation_tracker_xdk_.Reset(new XDKAllocationTracker(this, ids_.get(),
+                                names_.get(), stackDepth, retentions,
+                                strict_collection));
+  heap()->DisableInlineAllocation();
+  // init pre collected objects
+  allocation_tracker_xdk_->CollectFreedObjects(false, true);
+}
+
+
+void HeapProfiler::PushHeapObjectsXDKStats(OutputStream* stream) {
+  // get the garbage here
+  if (!allocation_tracker_xdk_.is_empty()) {
+    allocation_tracker_xdk_->CollectFreedObjects();
+    OutputStream::WriteResult result =
+        allocation_tracker_xdk_->SendChunk(stream);
+    // TODO(amalyshe): it's interesting why CDT can return kAbort. Need to
+    // investigate if we need add better error generation in the
+    // allocation_tracker_xdk_->SendChunk
+    if (result == OutputStream::kAbort) return;
+    stream->EndOfStream();
+  }
+}
+
+
+v8::internal::HeapEventXDK* HeapProfiler::StopHeapObjectsTrackingXDK() {
+  HeapEventXDK* event = NULL;
+  if (!allocation_tracker_xdk_.is_empty()) {
+    event = allocation_tracker_xdk_->stopTracking();
+    allocation_tracker_xdk_.Reset(NULL);
+    heap()->EnableInlineAllocation();
+  }
+  return event;
+}
+
+
 size_t HeapProfiler::GetMemorySizeUsedByProfiler() {
   size_t size = sizeof(*this);
   size += names_->GetUsedMemorySize();
@@ -145,9 +186,13 @@ SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Object> obj) {
 
 
 void HeapProfiler::ObjectMoveEvent(Address from, Address to, int size) {
-  bool known_object = ids_->MoveObject(from, to, size);
-  if (!known_object && !allocation_tracker_.is_empty()) {
-    allocation_tracker_->address_to_trace()->MoveObject(from, to, size);
+  if (allocation_tracker_xdk_.is_empty()) {
+    bool known_object = ids_->MoveObject(from, to, size);
+    if (!known_object && !allocation_tracker_.is_empty()) {
+      allocation_tracker_->address_to_trace()->MoveObject(from, to, size);
+    }
+  } else {
+    allocation_tracker_xdk_->OnMove(from, to, size);
   }
 }
 
@@ -157,6 +202,9 @@ void HeapProfiler::AllocationEvent(Address addr, int size) {
   if (!allocation_tracker_.is_empty()) {
     allocation_tracker_->AllocationEvent(addr, size);
   }
+  if (!allocation_tracker_xdk_.is_empty()) {
+    allocation_tracker_xdk_->OnAlloc(addr, size);
+  }
 }
 
 
index 4197d4d..88141cb 100644 (file)
@@ -13,6 +13,7 @@ namespace v8 {
 namespace internal {
 
 class HeapSnapshot;
+class HeapEventXDK;
 
 class HeapProfiler {
  public:
@@ -39,6 +40,11 @@ class HeapProfiler {
   StringsStorage* names() const { return names_.get(); }
 
   SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
+  void PushHeapObjectsXDKStats(OutputStream* stream);
+  void StartHeapObjectsTrackingXDK(int stackDepth, bool retentions,
+      bool strict_collection = false);
+  v8::internal::HeapEventXDK* StopHeapObjectsTrackingXDK();
+
   int GetSnapshotsCount();
   HeapSnapshot* GetSnapshot(int index);
   SnapshotObjectId GetSnapshotObjectId(Handle<Object> obj);
@@ -60,7 +66,8 @@ class HeapProfiler {
 
   bool is_tracking_object_moves() const { return is_tracking_object_moves_; }
   bool is_tracking_allocations() const {
-    return !allocation_tracker_.is_empty();
+    return (!allocation_tracker_.is_empty() ||
+        !allocation_tracker_xdk_.is_empty());
   }
 
   Handle<HeapObject> FindHeapObjectById(SnapshotObjectId id);
@@ -76,6 +83,7 @@ class HeapProfiler {
   unsigned next_snapshot_uid_;
   List<v8::HeapProfiler::WrapperInfoCallback> wrapper_callbacks_;
   SmartPointer<AllocationTracker> allocation_tracker_;
+  SmartPointer<XDKAllocationTracker> allocation_tracker_xdk_;
   bool is_tracking_object_moves_;
 };
 
index 3f7e622..9fe704f 100644 (file)
@@ -22,7 +22,7 @@ HeapSnapshot* HeapGraphEdge::snapshot() const {
 
 
 int HeapEntry::index() const {
-  return static_cast<int>(this - &snapshot_->entries().first());
+  return static_cast<int>(this - &entries_->first());
 }
 
 
index 4a4c914..d77e519 100644 (file)
@@ -47,6 +47,7 @@ void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) {
 const int HeapEntry::kNoEntry = -1;
 
 HeapEntry::HeapEntry(HeapSnapshot* snapshot,
+                     const List<HeapEntry>* entries,
                      Type type,
                      const char* name,
                      SnapshotObjectId id,
@@ -57,6 +58,7 @@ HeapEntry::HeapEntry(HeapSnapshot* snapshot,
       children_index_(-1),
       self_size_(self_size),
       snapshot_(snapshot),
+      entries_(entries),
       name_(name),
       id_(id),
       trace_node_id_(trace_node_id) { }
@@ -169,12 +171,16 @@ template <size_t ptr_size> struct SnapshotSizeConstants;
 
 template <> struct SnapshotSizeConstants<4> {
   static const int kExpectedHeapGraphEdgeSize = 12;
-  static const int kExpectedHeapEntrySize = 28;
+  // This variable reflects the size of the HeapEntry structure
+  // it is increased to the 4 bytes in case of 32bit arch and for
+  // 8 bytes for 64 bit arch because for isolating HeapEntry from
+  // snapshot we need to add one more pointer to the List* entries_
+  static const int kExpectedHeapEntrySize = 32;
 };
 
 template <> struct SnapshotSizeConstants<8> {
   static const int kExpectedHeapGraphEdgeSize = 24;
-  static const int kExpectedHeapEntrySize = 40;
+  static const int kExpectedHeapEntrySize = 48;
 };
 
 }  // namespace
@@ -269,7 +275,7 @@ HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
                                   SnapshotObjectId id,
                                   size_t size,
                                   unsigned trace_node_id) {
-  HeapEntry entry(this, type, name, id, size, trace_node_id);
+  HeapEntry entry(this, &this->entries(), type, name, id, size, trace_node_id);
   entries_.Add(entry);
   return &entries_.last();
 }
@@ -779,13 +785,14 @@ void HeapObjectsSet::SetTag(Object* obj, const char* tag) {
 
 
 V8HeapExplorer::V8HeapExplorer(
+    HeapProfiler* profiler,
     HeapSnapshot* snapshot,
     SnapshottingProgressReportingInterface* progress,
     v8::HeapProfiler::ObjectNameResolver* resolver)
-    : heap_(snapshot->profiler()->heap_object_map()->heap()),
+    : heap_(profiler->heap_object_map()->heap()),
       snapshot_(snapshot),
-      names_(snapshot_->profiler()->names()),
-      heap_object_map_(snapshot_->profiler()->heap_object_map()),
+      names_(profiler->names()),
+      heap_object_map_(profiler->heap_object_map()),
       progress_(progress),
       filler_(NULL),
       global_object_name_resolver_(resolver) {
@@ -891,12 +898,13 @@ HeapEntry* V8HeapExplorer::AddEntry(Address address,
 }
 
 
-class SnapshotFiller {
+class CDTSnapshotFiller: public SnapshotFiller {
  public:
-  explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
+  explicit CDTSnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
       : snapshot_(snapshot),
         names_(snapshot->profiler()->names()),
         entries_(entries) { }
+  virtual ~CDTSnapshotFiller() {}
   HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
     HeapEntry* entry = allocator->AllocateEntry(ptr);
     entries_->Pair(ptr, entry->index());
@@ -1855,11 +1863,15 @@ bool V8HeapExplorer::IterateAndExtractReferences(
   // Make sure builtin code objects get their builtin tags
   // first. Otherwise a particular JSFunction object could set
   // its custom name to a generic builtin.
-  RootsReferencesExtractor extractor(heap_);
-  heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
-  extractor.SetCollectingAllReferences();
-  heap_->IterateRoots(&extractor, VISIT_ALL);
-  extractor.FillReferences(this);
+  // TODO(amalyshe): this condition should be refactored for catching
+  // root extractor
+  if (snapshot_) {
+    RootsReferencesExtractor extractor(heap_);
+    heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
+    extractor.SetCollectingAllReferences();
+    heap_->IterateRoots(&extractor, VISIT_ALL);
+    extractor.FillReferences(this);
+  }
 
   // We have to do two passes as sometimes FixedArrays are used
   // to weakly hold their items, and it's impossible to distinguish
@@ -2085,10 +2097,12 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
 
 
 void V8HeapExplorer::SetRootGcRootsReference() {
-  filler_->SetIndexedAutoIndexReference(
-      HeapGraphEdge::kElement,
-      snapshot_->root()->index(),
-      snapshot_->gc_roots());
+  if (snapshot_) {
+    filler_->SetIndexedAutoIndexReference(
+        HeapGraphEdge::kElement,
+        snapshot_->root()->index(),
+        snapshot_->gc_roots());
+  }
 }
 
 
@@ -2103,10 +2117,12 @@ void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) {
 
 
 void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) {
-  filler_->SetIndexedAutoIndexReference(
-      HeapGraphEdge::kElement,
-      snapshot_->gc_roots()->index(),
-      snapshot_->gc_subroot(tag));
+  if (snapshot_) {
+    filler_->SetIndexedAutoIndexReference(
+        HeapGraphEdge::kElement,
+        snapshot_->gc_roots()->index(),
+        snapshot_->gc_subroot(tag));
+  }
 }
 
 
@@ -2258,11 +2274,12 @@ class GlobalHandlesExtractor : public ObjectVisitor {
 class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
  public:
   BasicHeapEntriesAllocator(
+      HeapProfiler* profiler,
       HeapSnapshot* snapshot,
       HeapEntry::Type entries_type)
     : snapshot_(snapshot),
-      names_(snapshot_->profiler()->names()),
-      heap_object_map_(snapshot_->profiler()->heap_object_map()),
+      names_(profiler->names()),
+      heap_object_map_(profiler->heap_object_map()),
       entries_type_(entries_type) {
   }
   virtual HeapEntry* AllocateEntry(HeapThing ptr);
@@ -2292,20 +2309,21 @@ HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) {
 
 
 NativeObjectsExplorer::NativeObjectsExplorer(
+    HeapProfiler* profiler,
     HeapSnapshot* snapshot,
     SnapshottingProgressReportingInterface* progress)
-    : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()),
+    : isolate_(profiler->heap_object_map()->heap()->isolate()),
       snapshot_(snapshot),
-      names_(snapshot_->profiler()->names()),
+      names_(profiler->names()),
       progress_(progress),
       embedder_queried_(false),
       objects_by_info_(RetainedInfosMatch),
       native_groups_(StringsMatch),
       filler_(NULL) {
   synthetic_entries_allocator_ =
-      new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic);
+      new BasicHeapEntriesAllocator(profiler, snapshot, HeapEntry::kSynthetic);
   native_entries_allocator_ =
-      new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative);
+      new BasicHeapEntriesAllocator(profiler, snapshot, HeapEntry::kNative);
 }
 
 
@@ -2533,15 +2551,18 @@ void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
 
 
 HeapSnapshotGenerator::HeapSnapshotGenerator(
+    HeapProfiler* profiler,
     HeapSnapshot* snapshot,
     v8::ActivityControl* control,
     v8::HeapProfiler::ObjectNameResolver* resolver,
-    Heap* heap)
+    Heap* heap,
+    SnapshotFiller* filler)
     : snapshot_(snapshot),
       control_(control),
-      v8_heap_explorer_(snapshot_, this, resolver),
-      dom_explorer_(snapshot_, this),
-      heap_(heap) {
+      v8_heap_explorer_(profiler, snapshot_, this, resolver),
+      dom_explorer_(profiler, snapshot_, this),
+      heap_(heap),
+      filler_(filler) {
 }
 
 
@@ -2570,12 +2591,16 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
   debug_heap->Verify();
 #endif
 
-  snapshot_->AddSyntheticRootEntries();
+  if (snapshot_) {
+    snapshot_->AddSyntheticRootEntries();
+  }
 
   if (!FillReferences()) return false;
 
-  snapshot_->FillChildren();
-  snapshot_->RememberLastJSObjectId();
+  if (snapshot_) {
+    snapshot_->FillChildren();
+    snapshot_->RememberLastJSObjectId();
+  }
 
   progress_counter_ = progress_total_;
   if (!ProgressReport(true)) return false;
@@ -2611,9 +2636,16 @@ void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
 
 
 bool HeapSnapshotGenerator::FillReferences() {
-  SnapshotFiller filler(snapshot_, &entries_);
-  return v8_heap_explorer_.IterateAndExtractReferences(&filler)
-      && dom_explorer_.IterateAndExtractReferences(&filler);
+  if (!filler_) {
+    CDTSnapshotFiller filler(snapshot_, &entries_);
+    return v8_heap_explorer_.IterateAndExtractReferences(&filler)
+        && dom_explorer_.IterateAndExtractReferences(&filler);
+  } else {
+    // TODO(amalyshe): finally this need to be returned back when XDK heap
+    // profiler supports toot extractor
+    // v8_heap_explorer_.AddRootEntries(filler_);
+    return v8_heap_explorer_.IterateAndExtractReferences(filler_);
+  }
 }
 
 
index 3e4ce71..e649317 100644 (file)
@@ -11,6 +11,7 @@ namespace v8 {
 namespace internal {
 
 class AllocationTracker;
+class XDKAllocationTracker;
 class AllocationTraceNode;
 class HeapEntry;
 class HeapSnapshot;
@@ -90,6 +91,7 @@ class HeapEntry BASE_EMBEDDED {
 
   HeapEntry() { }
   HeapEntry(HeapSnapshot* snapshot,
+            const List<HeapEntry>* entries,
             Type type,
             const char* name,
             SnapshotObjectId id,
@@ -129,6 +131,7 @@ class HeapEntry BASE_EMBEDDED {
   int children_index_;
   size_t self_size_;
   HeapSnapshot* snapshot_;
+  const List<HeapEntry>* entries_;
   const char* name_;
   SnapshotObjectId id_;
   // id of allocation stack trace top node
@@ -323,11 +326,36 @@ class SnapshottingProgressReportingInterface {
   virtual bool ProgressReport(bool force) = 0;
 };
 
+class SnapshotFiller {
+ public:
+  virtual ~SnapshotFiller() {}
+
+  virtual HeapEntry* AddEntry(HeapThing ptr,
+                              HeapEntriesAllocator* allocator) = 0;
+  virtual HeapEntry* FindEntry(HeapThing ptr) = 0;
+  virtual HeapEntry* FindOrAddEntry(HeapThing ptr,
+                                    HeapEntriesAllocator* allocator) = 0;
+  virtual void SetIndexedReference(HeapGraphEdge::Type type,
+                           int parent,
+                           int index,
+                           HeapEntry* child_entry) = 0;
+  virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
+                                    int parent,
+                                    HeapEntry* child_entry) = 0;
+  virtual void SetNamedReference(HeapGraphEdge::Type type,
+                         int parent,
+                         const char* reference_name,
+                         HeapEntry* child_entry) = 0;
+  virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
+                                  int parent,
+                                  HeapEntry* child_entry) = 0;
+};
 
 // An implementation of V8 heap graph extractor.
 class V8HeapExplorer : public HeapEntriesAllocator {
  public:
-  V8HeapExplorer(HeapSnapshot* snapshot,
+  V8HeapExplorer(HeapProfiler* profiler,
+                 HeapSnapshot* snapshot,
                  SnapshottingProgressReportingInterface* progress,
                  v8::HeapProfiler::ObjectNameResolver* resolver);
   virtual ~V8HeapExplorer();
@@ -470,7 +498,8 @@ class NativeGroupRetainedObjectInfo;
 // An implementation of retained native objects extractor.
 class NativeObjectsExplorer {
  public:
-  NativeObjectsExplorer(HeapSnapshot* snapshot,
+  NativeObjectsExplorer(HeapProfiler* profiler,
+                        HeapSnapshot* snapshot,
                         SnapshottingProgressReportingInterface* progress);
   virtual ~NativeObjectsExplorer();
   void AddRootEntries(SnapshotFiller* filler);
@@ -527,10 +556,12 @@ class NativeObjectsExplorer {
 
 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
  public:
-  HeapSnapshotGenerator(HeapSnapshot* snapshot,
+  HeapSnapshotGenerator(HeapProfiler* profiler,
+                        HeapSnapshot* snapshot,
                         v8::ActivityControl* control,
                         v8::HeapProfiler::ObjectNameResolver* resolver,
-                        Heap* heap);
+                        Heap* heap,
+                        SnapshotFiller* filler = NULL);
   bool GenerateSnapshot();
 
  private:
@@ -549,6 +580,7 @@ class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
   int progress_counter_;
   int progress_total_;
   Heap* heap_;
+  SnapshotFiller* filler_;
 
   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
 };
index b27a009..f7c36b9 100644 (file)
@@ -16,7 +16,8 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
                      const char* resource_name,
                      int line_number,
                      int column_number,
-                     JITLineInfoTable* line_info)
+                     JITLineInfoTable* line_info,
+                     Address instruction_start)
     : tag_(tag),
       builtin_id_(Builtins::builtin_count),
       name_prefix_(name_prefix),
@@ -28,7 +29,8 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
       script_id_(v8::UnboundScript::kNoScriptId),
       no_frame_ranges_(NULL),
       bailout_reason_(kEmptyBailoutReason),
-      line_info_(line_info) { }
+      line_info_(line_info),
+      instruction_start_(instruction_start) { }
 
 
 bool CodeEntry::is_js_function_tag(Logger::LogEventsAndTags tag) {
index 3f79c6a..61743a5 100644 (file)
@@ -132,6 +132,31 @@ HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) {
 }
 
 
+JITLineInfoTable::JITLineInfoTable() {}
+
+
+JITLineInfoTable::~JITLineInfoTable() {}
+
+
+void JITLineInfoTable::SetPosition(int pc_offset, int line) {
+  DCHECK(pc_offset >= 0);
+  DCHECK(line > 0);  // The 1-based number of the source line.
+  if (GetSourceLineNumber(pc_offset) != line) {
+    pc_offset_map_.insert(std::make_pair(pc_offset, line));
+  }
+}
+
+
+int JITLineInfoTable::GetSourceLineNumber(int pc_offset) const {
+  PcOffsetMap::const_iterator it = pc_offset_map_.lower_bound(pc_offset);
+  if (it == pc_offset_map_.end()) {
+    if (pc_offset_map_.empty()) return v8::CpuProfileNode::kNoLineNumberInfo;
+    return (--pc_offset_map_.end())->second;
+  }
+  return it->second;
+}
+
+
 const char* const CodeEntry::kEmptyNamePrefix = "";
 const char* const CodeEntry::kEmptyResourceName = "";
 const char* const CodeEntry::kEmptyBailoutReason = "";
@@ -183,7 +208,7 @@ void CodeEntry::SetBuiltinId(Builtins::Name id) {
 
 
 int CodeEntry::GetSourceLine(int pc_offset) const {
-  if (line_info_ && !line_info_->Empty()) {
+  if (line_info_ && !line_info_->empty()) {
     return line_info_->GetSourceLineNumber(pc_offset);
   }
   return v8::CpuProfileNode::kNoLineNumberInfo;
@@ -216,7 +241,7 @@ void ProfileNode::IncrementLineTicks(int src_line) {
   // Increment a hit counter of a certain source line.
   // Add a new source line if not found.
   HashMap::Entry* e =
-    line_ticks_.Lookup(reinterpret_cast<void*>(src_line), src_line, true);
+      line_ticks_.Lookup(reinterpret_cast<void*>(src_line), src_line, true);
   DCHECK(e);
   e->value = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(e->value) + 1);
 }
@@ -228,7 +253,7 @@ bool ProfileNode::GetLineTicks(v8::CpuProfileNode::LineTick* entries,
 
   unsigned line_count = line_ticks_.occupancy();
 
-  if (line_count == 0) return false;
+  if (line_count == 0) return true;
   if (length < line_count) return false;
 
   v8::CpuProfileNode::LineTick* entry = entries;
@@ -591,14 +616,16 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(
       const char* resource_name,
       int line_number,
       int column_number,
-      JITLineInfoTable* line_info) {
+      JITLineInfoTable* line_info,
+      Address instruction_start) {
   CodeEntry* code_entry = new CodeEntry(tag,
                                         name,
                                         name_prefix,
                                         resource_name,
                                         line_number,
                                         column_number,
-                                        line_info);
+                                        line_info,
+                                        instruction_start);
   code_entries_.Add(code_entry);
   return code_entry;
 }
@@ -641,8 +668,9 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
   // the same JS function. The line number information associated with
   // the latest version of generated code is used to find a source line number
   // for a JS function. Then, the detected source line is passed to
-  // ProfileNode to accumulate the samples.
+  // ProfileNode to increase the tick count for this source line.
   int src_line = v8::CpuProfileNode::kNoLineNumberInfo;
+  bool src_line_not_found = true;
 
   if (sample.pc != NULL) {
     if (sample.has_external_callback && sample.state == EXTERNAL &&
@@ -660,9 +688,8 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
       // frame. Check for this case and just skip such samples.
       if (pc_entry) {
         List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
-        Code* code = Code::cast(HeapObject::FromAddress(start));
-        int pc_offset = static_cast<int>(sample.pc - code->instruction_start());
-        src_line = pc_entry->GetSourceLine(pc_offset);
+        int pc_offset =
+            static_cast<int>(sample.pc - pc_entry->instruction_start());
         if (ranges) {
           for (int i = 0; i < ranges->length(); i++) {
             OffsetRange& range = ranges->at(i);
@@ -671,6 +698,11 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
             }
           }
         }
+        src_line = pc_entry->GetSourceLine(pc_offset);
+        if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
+          src_line = pc_entry->line_number();
+        }
+        src_line_not_found = false;
         *entry++ = pc_entry;
 
         if (pc_entry->builtin_id() == Builtins::kFunctionCall ||
@@ -687,8 +719,6 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
       }
     }
 
-    bool src_line_not_found = src_line == v8::CpuProfileNode::kNoLineNumberInfo;
-
     for (const Address* stack_pos = sample.stack,
            *stack_end = stack_pos + sample.frames_count;
          stack_pos != stack_end;
@@ -697,11 +727,10 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
       *entry = code_map_.FindEntry(*stack_pos, &start);
 
       // Skip unresolved frames (e.g. internal frame) and get source line of
-      // the JS caller.
+      // the first JS caller.
       if (src_line_not_found && *entry) {
-        Code* code = Code::cast(HeapObject::FromAddress(start));
         int pc_offset =
-            static_cast<int>(*stack_pos - code->instruction_start());
+            static_cast<int>(*stack_pos - (*entry)->instruction_start());
         src_line = (*entry)->GetSourceLine(pc_offset);
         if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
           src_line = (*entry)->line_number();
index f973eb2..897ce07 100644 (file)
@@ -49,24 +49,13 @@ class StringsStorage {
 // the source line.
 class JITLineInfoTable : public Malloced {
  public:
-  JITLineInfoTable() {}
-  ~JITLineInfoTable() {}
+  JITLineInfoTable();
+  ~JITLineInfoTable();
 
-  void SetPosition(int pc_offset, int line) {
-    DCHECK(pc_offset >= 0);
-    DCHECK(line > 0);  // The 1-based number of the source line.
-    pc_offset_map_.insert(std::make_pair(pc_offset, line));
-  }
+  void SetPosition(int pc_offset, int line);
+  int GetSourceLineNumber(int pc_offset) const;
 
-  int GetSourceLineNumber(int pc_offset) const {
-    PcOffsetMap::const_iterator it = pc_offset_map_.lower_bound(pc_offset);
-    if (it == pc_offset_map_.end()) {
-      return v8::CpuProfileNode::kNoLineNumberInfo;
-    }
-    return it->second;
-  }
-
-  bool Empty() const { return pc_offset_map_.empty(); }
+  bool empty() const { return pc_offset_map_.empty(); }
 
  private:
   // pc_offset -> source line
@@ -84,7 +73,8 @@ class CodeEntry {
                    const char* resource_name = CodeEntry::kEmptyResourceName,
                    int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
                    int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
-                   JITLineInfoTable* line_info = NULL);
+                   JITLineInfoTable* line_info = NULL,
+                   Address instruction_start = NULL);
   ~CodeEntry();
 
   bool is_js_function() const { return is_js_function_tag(tag_); }
@@ -118,6 +108,8 @@ class CodeEntry {
 
   int GetSourceLine(int pc_offset) const;
 
+  Address instruction_start() const { return instruction_start_; }
+
   static const char* const kEmptyNamePrefix;
   static const char* const kEmptyResourceName;
   static const char* const kEmptyBailoutReason;
@@ -135,6 +127,7 @@ class CodeEntry {
   List<OffsetRange>* no_frame_ranges_;
   const char* bailout_reason_;
   JITLineInfoTable* line_info_;
+  Address instruction_start_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeEntry);
 };
@@ -329,7 +322,8 @@ class CpuProfilesCollection {
       const char* resource_name = CodeEntry::kEmptyResourceName,
       int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
       int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
-      JITLineInfoTable* line_info = NULL);
+      JITLineInfoTable* line_info = NULL,
+      Address instruction_start = NULL);
 
   // Called from profile generator thread.
   void AddPathToCurrentProfiles(base::TimeTicks timestamp,
diff --git a/src/v8/src/xdk-allocation.cc b/src/v8/src/xdk-allocation.cc
new file mode 100644 (file)
index 0000000..311a592
--- /dev/null
@@ -0,0 +1,539 @@
+// Copyright 2014 the V8 project authors. All rights reserved.\r
+// Use of this source code is governed by a BSD-style license that can be\r
+// found in the LICENSE file.\r
+\r
+#include <sstream>\r
+#include <string>\r
+\r
+#include "src/v8.h"\r
+\r
+#include "src/xdk-allocation.h"\r
+\r
+#include "frames-inl.h"\r
+#include "src/xdk-utils.h"\r
+\r
+namespace v8 {\r
+namespace internal {\r
+\r
+XDKAllocationTracker::XDKAllocationTracker(HeapProfiler* heap_profiler,\r
+                                           HeapObjectsMap *ids,\r
+                                           StringsStorage *names,\r
+                                           int stackDepth,\r
+                                           bool collectRetention,\r
+                                           bool strict_collection)\r
+    : heap_profiler_(heap_profiler),\r
+    ids_(ids),\r
+    names_(names),\r
+    stackDepth_(stackDepth),\r
+    collectRetention_(collectRetention),\r
+    strict_collection_(strict_collection) {\r
+  references_ = new References();\r
+  aggregated_chunks_ = new AggregatedChunks();\r
+  runtime_info_ = new RuntimeInfo(aggregated_chunks_);\r
+  symbols_ = new SymbolsStorage(ids_->heap(), names_);\r
+  collectedStacks_ = new ShadowStack();\r
+  classNames_ = new ClassNames(names_);\r
+\r
+  List<unsigned> stack_ooc;\r
+  stack_ooc.Add(symbols_->registerSymInfo(1, "OutOfContext", "NoSource",\r
+                                          0, 0));\r
+  outOfContextFrame_ = collectedStacks_->registerStack(stack_ooc);\r
+\r
+  List<unsigned> stack_abc;\r
+  stack_abc.Add(symbols_->registerSymInfo(2, "AllocatedBeforeCollection",\r
+                                          "NoSource", 0, 0));\r
+  AllocatedBeforeCollectionFrame_ = collectedStacks_->registerStack(stack_abc);\r
+\r
+  runtime_info_->InitABCFrame(AllocatedBeforeCollectionFrame_);\r
+\r
+  baseTime_ = v8::base::Time::Now();\r
+  latest_delta_ = 0;\r
+}\r
+\r
+\r
+XDKAllocationTracker::~XDKAllocationTracker() {\r
+  delete collectedStacks_;\r
+  delete classNames_;\r
+  delete aggregated_chunks_;\r
+  delete runtime_info_;\r
+  delete symbols_;\r
+  delete references_;\r
+}\r
+\r
+\r
+// Heap profiler regularly takes time for storing when object was allocated,\r
+// deallocated, when object's retention snapshot was taken, etc\r
+unsigned int XDKAllocationTracker::GetTimeDelta() {\r
+  v8::base::TimeDelta td = v8::base::Time::Now() - baseTime_;\r
+  return static_cast<unsigned int>(td.InMilliseconds());\r
+}\r
+\r
+\r
+void XDKAllocationTracker::OnAlloc(Address addr, int size) {\r
+  DisallowHeapAllocation no_alloc;\r
+  Heap *heap = ids_->heap();\r
+\r
+  // below call saves from the crash during StackTraceFrameIterator creation\r
+  // Mark the new block as FreeSpace to make sure the heap is iterable\r
+  // while we are capturing stack trace.\r
+  FreeListNode::FromAddress(addr)->set_size(heap, size);\r
+\r
+  Isolate *isolate = heap->isolate();\r
+  StackTraceFrameIterator it(isolate);\r
+  List<unsigned> stack;\r
+\r
+  // TODO(amalyshe): checking of isolate->handle_scope_data()->level is quite\r
+  // artificial. need to understand when we can have such behaviour\r
+  // if level == 0 we will crash in getting of source info\r
+  while (isolate->handle_scope_data()->level && !it.done() &&\r
+      stack.length() < stackDepth_) {\r
+    JavaScriptFrame *frame = it.frame();\r
+    if (!frame->function())\r
+      break;\r
+    SharedFunctionInfo *shared = frame->function()->shared();\r
+    if (!shared)\r
+      break;\r
+\r
+    stack.Add(symbols_->FindOrRegisterFrame(frame));\r
+    it.Advance();\r
+  }\r
+\r
+  unsigned sid;\r
+  if (!stack.is_empty()) {\r
+    sid = collectedStacks_->registerStack(stack);\r
+  } else {\r
+    sid = outOfContextFrame_;\r
+  }\r
+\r
+  latest_delta_ = GetTimeDelta();\r
+\r
+  PostCollectedInfo* info = runtime_info_->AddPostCollectedInfo(addr,\r
+                                                                latest_delta_);\r
+  info->size_ = size;\r
+  info->timeStamp_ = latest_delta_;\r
+  info->stackId_ = sid;\r
+  info->className_ = (unsigned int)-1;\r
+  info->dirty_ = false;\r
+}\r
+\r
+\r
+void XDKAllocationTracker::OnMove(Address from, Address to, int size) {\r
+  DisallowHeapAllocation no_alloc;\r
+  // look for the prev address\r
+  PostCollectedInfo* info_from = runtime_info_->FindPostCollectedInfo(from);\r
+  if (info_from == NULL) {\r
+    return;\r
+  }\r
+\r
+  runtime_info_->AddPostCollectedInfo(to, latest_delta_, info_from);\r
+  runtime_info_->RemoveInfo(from);\r
+}\r
+\r
+\r
+HeapEventXDK* XDKAllocationTracker::stopTracking() {\r
+  std::string symbols, types, frames, chunks, retentions;\r
+  SerializeChunk(&symbols, &types, &frames, &chunks, &retentions);\r
+  CollectFreedObjects(true);\r
+  std::string symbolsA, typesA, framesA, chunksA, retentionsA;\r
+  SerializeChunk(&symbolsA, &typesA, &framesA, &chunksA, &retentionsA, true);\r
+\r
+  // TODO(amalyshe): check who releases this object - new HeapEventXDK\r
+  return (new HeapEventXDK(GetTimeDelta(), symbols+symbolsA, types+typesA,\r
+      frames+framesA, chunks+chunksA, ""));\r
+}\r
+\r
+\r
+void XDKAllocationTracker::CollectFreedObjects(bool bAll, bool initPreCollect) {\r
+  clearIndividualReteiners();\r
+  if (collectRetention_) {\r
+    XDKSnapshotFiller filler(ids_, names_, this);\r
+    HeapSnapshotGenerator generator(heap_profiler_, NULL, NULL, NULL,\r
+                                    ids_->heap(), &filler);\r
+    generator.GenerateSnapshot();\r
+  }\r
+\r
+  Heap *heap = ids_->heap();\r
+  if (!heap) {\r
+    return;\r
+  }\r
+\r
+  unsigned int ts = GetTimeDelta();\r
+  if (bAll) {\r
+    ts += RETAINED_DELTA;\r
+  }\r
+\r
+  // CDT heap profiler calls CollectAllGarbage twice because after the first\r
+  // pass there are weak retained object not collected, but due to perf issues\r
+  // and because we do garbage collection regularly, we leave here only one call\r
+  // only for strict collection like in test where we need to make sure that\r
+  // object is definitely collected, we collect twice\r
+  heap->CollectAllGarbage(\r
+      Heap::kMakeHeapIterableMask,\r
+      "XDKAllocationTracker::CollectFreedObjects");\r
+  if (strict_collection_) {\r
+    heap->CollectAllGarbage(\r
+        Heap::kMakeHeapIterableMask,\r
+        "XDKAllocationTracker::CollectFreedObjects");\r
+  }\r
+  std::map<Address, RefSet> individualReteiners;\r
+\r
+  // TODO(amalyshe): check what DisallowHeapAllocation no_alloc means because in\r
+  // standalone v8 this part is crashed if DisallowHeapAllocation is defined\r
+  // DisallowHeapAllocation no_alloc;\r
+  if (!bAll) {\r
+    HeapIterator iterator(heap);\r
+    HeapObject* obj = iterator.next();\r
+    for (;\r
+         obj != NULL;\r
+         obj = iterator.next()) {\r
+      Address addr = obj->address();\r
+\r
+      PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(addr);\r
+      if (!info) {\r
+        // if we don't find info, we consider it as pre collection allocated\r
+        // object. need to add to the full picture for retentions\r
+        if (initPreCollect) {\r
+          info = runtime_info_->AddPreCollectionInfo(addr, obj->Size());\r
+        }\r
+      }\r
+\r
+      if (info) {\r
+        info->dirty_ = true;\r
+      }\r
+      // check of the class name and its initialization\r
+      if ((info && info->className_ == (unsigned)-1) || !info) {\r
+        InitClassName(addr, ts, obj->Size());\r
+      }\r
+    }\r
+  }\r
+\r
+  if (collectRetention_) {\r
+    std::map<Address, RefSet>::const_iterator citir =\r
+        individualReteiners_.begin();\r
+    while (citir != individualReteiners_.end()) {\r
+      PostCollectedInfo* infoChild =\r
+          runtime_info_->FindPostCollectedInfo(citir->first);\r
+      if (infoChild) {\r
+        RefId rfId;\r
+        rfId.stackId_ = infoChild->stackId_;\r
+        rfId.classId_ = infoChild->className_;\r
+\r
+        references_->addReference(rfId, citir->second, infoChild->timeStamp_);\r
+      }\r
+      citir++;\r
+    }\r
+  }\r
+\r
+  runtime_info_->CollectGarbaged(ts);\r
+}\r
+\r
+\r
+void XDKAllocationTracker::SerializeChunk(std::string* symbols,\r
+                                          std::string* types,\r
+                                          std::string* frames,\r
+                                          std::string* chunks,\r
+                                          std::string* retentions,\r
+                                          bool final) {\r
+  if (final) {\r
+    *symbols = symbols_->SerializeChunk();\r
+    *types = classNames_->SerializeChunk();\r
+  }\r
+  *frames = collectedStacks_->SerializeChunk();\r
+  *chunks = aggregated_chunks_->SerializeChunk();\r
+\r
+  *retentions = references_->serialize();\r
+  std::stringstream retentionsT;\r
+  retentionsT << GetTimeDelta() << std::endl << retentions->c_str();\r
+  *retentions = retentionsT.str();\r
+  references_->clear();\r
+}\r
+\r
+\r
+OutputStream::WriteResult XDKAllocationTracker::SendChunk(\r
+    OutputStream* stream) {\r
+  // go over all aggregated_ and send data to the stream\r
+  std::string symbols, types, frames, chunks, retentions;\r
+  SerializeChunk(&symbols, &types, &frames, &chunks, &retentions);\r
+\r
+  OutputStream::WriteResult ret = stream->WriteHeapXDKChunk(\r
+      symbols.c_str(), symbols.length(),\r
+      frames.c_str(), frames.length(),\r
+      types.c_str(), types.length(),\r
+      chunks.c_str(), chunks.length(),\r
+      retentions.c_str(), retentions.length());\r
+  return ret;\r
+}\r
+\r
+\r
+unsigned XDKAllocationTracker::GetTraceNodeId(Address address) {\r
+    PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address);\r
+    if (info) {\r
+      return info->stackId_;\r
+    } else {\r
+      return AllocatedBeforeCollectionFrame_;\r
+    }\r
+}\r
+\r
+\r
+void XDKAllocationTracker::clearIndividualReteiners() {\r
+  individualReteiners_.clear();\r
+}\r
+\r
+\r
+std::map<Address, RefSet>* XDKAllocationTracker::GetIndividualReteiners() {\r
+  return &individualReteiners_;\r
+}\r
+\r
+\r
+unsigned XDKAllocationTracker::FindClassName(Address address) {\r
+  PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address);\r
+  if (info) {\r
+    return info->className_;\r
+  } else {\r
+    return (unsigned)-1;\r
+  }\r
+}\r
+\r
+\r
+unsigned XDKAllocationTracker::InitClassName(Address address, unsigned ts,\r
+                                             unsigned size) {\r
+  unsigned id = -2;\r
+  PostCollectedInfo* info = runtime_info_->FindPostCollectedInfo(address);\r
+  if (!info) {\r
+    info = runtime_info_->AddPostCollectedInfo(address, ts);\r
+    info->className_ = -1;\r
+    info->stackId_ = outOfContextFrame_;\r
+    info->timeStamp_ = ts;\r
+    info->size_ = size;\r
+  }\r
+  if (info->className_ == (unsigned)-1) {\r
+    String* str = classNames_->GetConstructorName(address);\r
+    if (str) {\r
+      // get const char*, it's safe because pointer will be retained in the\r
+      // name_ until it is destroyed\r
+      id = classNames_->registerName(names_->GetName(str));\r
+    }\r
+  }\r
+  info->className_ = id;\r
+  return id;\r
+}\r
+\r
+\r
+unsigned XDKAllocationTracker::FindOrInitClassName(Address address,\r
+                                                   unsigned ts) {\r
+  unsigned id = FindClassName(address);\r
+  if (id == (unsigned)-1) {\r
+    // TODO(amalyshe) check if 0 size here is appropriate\r
+    id = InitClassName(address, ts, 0);\r
+  }\r
+  return id;\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+// this is almost a copy and duplication of\r
+// V8HeapExplorer::AddEntry. refactoring is impossible because\r
+// heap-snapshot-generator rely on it's structure which is not fully suitable\r
+// for us.\r
+HeapEntry* XDKSnapshotFiller::AddEntry(HeapThing ptr,\r
+                                       HeapEntriesAllocator* allocator) {\r
+  HeapObject* object = reinterpret_cast<HeapObject*>(ptr);\r
+  if (object->IsJSFunction()) {\r
+    JSFunction* func = JSFunction::cast(object);\r
+    SharedFunctionInfo* shared = func->shared();\r
+    const char* name = shared->bound() ? "native_bind" :\r
+        names_->GetName(String::cast(shared->name()));\r
+    return AddEntry(ptr, object, HeapEntry::kClosure, name);\r
+  } else if (object->IsJSRegExp()) {\r
+    JSRegExp* re = JSRegExp::cast(object);\r
+    return AddEntry(ptr, object,\r
+                    HeapEntry::kRegExp,\r
+                    names_->GetName(re->Pattern()));\r
+  } else if (object->IsJSObject()) {\r
+    return AddEntry(ptr, object, HeapEntry::kObject, "");\r
+  } else if (object->IsString()) {\r
+    String* string = String::cast(object);\r
+    if (string->IsConsString())\r
+      return AddEntry(ptr, object,\r
+                      HeapEntry::kConsString,\r
+                      "(concatenated string)");\r
+    if (string->IsSlicedString())\r
+      return AddEntry(ptr, object,\r
+                      HeapEntry::kSlicedString,\r
+                      "(sliced string)");\r
+    return AddEntry(ptr, object,\r
+                    HeapEntry::kString,\r
+                    names_->GetName(String::cast(object)));\r
+  } else if (object->IsSymbol()) {\r
+    return AddEntry(ptr, object, HeapEntry::kSymbol, "symbol");\r
+  } else if (object->IsCode()) {\r
+    return AddEntry(ptr, object, HeapEntry::kCode, "");\r
+  } else if (object->IsSharedFunctionInfo()) {\r
+    String* name = String::cast(SharedFunctionInfo::cast(object)->name());\r
+    return AddEntry(ptr, object,\r
+                    HeapEntry::kCode,\r
+                    names_->GetName(name));\r
+  } else if (object->IsScript()) {\r
+    Object* name = Script::cast(object)->name();\r
+    return AddEntry(ptr, object,\r
+                    HeapEntry::kCode,\r
+                    name->IsString()\r
+                        ? names_->GetName(String::cast(name))\r
+                        : "");\r
+  } else if (object->IsNativeContext()) {\r
+    return AddEntry(ptr, object, HeapEntry::kHidden, "system / NativeContext");\r
+  } else if (object->IsContext()) {\r
+    return AddEntry(ptr, object, HeapEntry::kObject, "system / Context");\r
+  } else if (object->IsFixedArray() ||\r
+             object->IsFixedDoubleArray() ||\r
+             object->IsByteArray() ||\r
+             object->IsExternalArray()) {\r
+    return AddEntry(ptr, object, HeapEntry::kArray, "");\r
+  } else if (object->IsHeapNumber()) {\r
+    return AddEntry(ptr, object, HeapEntry::kHeapNumber, "number");\r
+  }\r
+\r
+  return AddEntry(ptr, object, HeapEntry::kHidden, "system / NOT SUPORTED YET");\r
+}\r
+\r
+\r
+HeapEntry* XDKSnapshotFiller::AddEntry(HeapThing thing,\r
+                    HeapObject* object,\r
+                    HeapEntry::Type type,\r
+                    const char* name) {\r
+  Address address = object->address();\r
+  unsigned trace_node_id = 0;\r
+  trace_node_id = allocation_tracker_->GetTraceNodeId(address);\r
+\r
+  // cannot store pointer in the map because List reallcoates content regularly\r
+  // and the only  one way to find the entry - by index. so, index is cached in\r
+  // the map\r
+  // TODO(amalyshe): need to reuse type. it seems it is important\r
+  HeapEntry entry(NULL, &heap_entries_list_, type, name, 0, 0,\r
+                  trace_node_id);\r
+  heap_entries_list_.Add(entry);\r
+  HeapEntry* pEntry = &heap_entries_list_.last();\r
+\r
+  HashMap::Entry* cache_entry = heap_entries_.Lookup(thing, Hash(thing), true);\r
+  DCHECK(cache_entry->value == NULL);\r
+  int index = pEntry->index();\r
+  cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(index));\r
+\r
+  // TODO(amalyshe): it seems this storage might be optimized\r
+  HashMap::Entry* address_entry = index_to_address_.Lookup(\r
+      reinterpret_cast<void*>(index+1), HashInt(index+1), true);\r
+  address_entry->value = reinterpret_cast<void*>(address);\r
+\r
+  return pEntry;\r
+}\r
+\r
+\r
+HeapEntry* XDKSnapshotFiller::FindEntry(HeapThing thing) {\r
+  HashMap::Entry* cache_entry = heap_entries_.Lookup(thing, Hash(thing), false);\r
+  if (cache_entry == NULL) return NULL;\r
+  return &heap_entries_list_[static_cast<int>(\r
+      reinterpret_cast<intptr_t>(cache_entry->value))];\r
+}\r
+\r
+\r
+HeapEntry* XDKSnapshotFiller::FindOrAddEntry(HeapThing ptr,\r
+                                             HeapEntriesAllocator* allocator) {\r
+  HeapEntry* entry = FindEntry(ptr);\r
+  return entry != NULL ? entry : AddEntry(ptr, allocator);\r
+}\r
+\r
+\r
+void XDKSnapshotFiller::SetIndexedReference(HeapGraphEdge::Type type,\r
+    int parent,\r
+    int index,\r
+    HeapEntry* child_entry) {\r
+  if (child_entry->trace_node_id() < 3) {\r
+    return;\r
+  }\r
+  HashMap::Entry* address_entry_child = index_to_address_.Lookup(\r
+      reinterpret_cast<void*>(child_entry->index()+1),\r
+      HashInt(child_entry->index()+1), false);\r
+  DCHECK(address_entry_child != NULL);\r
+  if (!address_entry_child) {\r
+    return;\r
+  }\r
+\r
+  Address child_addr = reinterpret_cast<Address>(address_entry_child->value);\r
+\r
+  std::map<Address, RefSet>* individualReteiners =\r
+      allocation_tracker_->GetIndividualReteiners();\r
+  // get the parent's address, constructor name and form the RefId\r
+  HashMap::Entry* address_entry = index_to_address_.Lookup(\r
+      reinterpret_cast<void*>(parent+1), HashInt(parent+1), false);\r
+  DCHECK(address_entry != NULL);\r
+  if (!address_entry) {\r
+    return;\r
+  }\r
+  HeapEntry* parent_entry = &(heap_entries_list_[parent]);\r
+  Address parent_addr = reinterpret_cast<Address>(address_entry->value);\r
+  RefId parent_ref_id;\r
+  parent_ref_id.stackId_ = parent_entry->trace_node_id();\r
+  parent_ref_id.classId_ =\r
+      allocation_tracker_->FindOrInitClassName(parent_addr, 0);\r
+\r
+  std::stringstream str;\r
+  str << index << " element in Array";\r
+  parent_ref_id.field_ = str.str();\r
+\r
+  (*individualReteiners)[child_addr].references_.insert(parent_ref_id);\r
+}\r
+\r
+\r
+void XDKSnapshotFiller::SetIndexedAutoIndexReference(HeapGraphEdge::Type type,\r
+    int parent,\r
+    HeapEntry* child_entry) {\r
+}\r
+\r
+\r
+void XDKSnapshotFiller::SetNamedReference(HeapGraphEdge::Type type,\r
+    int parent,\r
+    const char* reference_name,\r
+    HeapEntry* child_entry) {\r
+  if (child_entry->trace_node_id() < 3) {\r
+    return;\r
+  }\r
+\r
+  std::map<Address, RefSet>* individualReteiners =\r
+      allocation_tracker_->GetIndividualReteiners();\r
+  // get the parent's address, constructor name and form the RefId\r
+  HashMap::Entry* address_entry = index_to_address_.Lookup(\r
+      reinterpret_cast<void*>(parent+1), HashInt(parent+1), false);\r
+  DCHECK(address_entry != NULL);\r
+  if (!address_entry) {\r
+    return;\r
+  }\r
+  HeapEntry* parent_entry = &(heap_entries_list_[parent]);\r
+  Address parent_addr = reinterpret_cast<Address>(address_entry->value);\r
+  RefId parent_ref_id;\r
+  parent_ref_id.stackId_ = parent_entry->trace_node_id();\r
+  // TODO(amalyshe): need to get access to classNames_\r
+  parent_ref_id.classId_ =\r
+      allocation_tracker_->FindOrInitClassName(parent_addr, 0);\r
+  parent_ref_id.field_ = reference_name;\r
+\r
+  HashMap::Entry* address_entry_child = index_to_address_.Lookup(\r
+      reinterpret_cast<void*>(child_entry->index()+1),\r
+      HashInt(child_entry->index()+1), false);\r
+  DCHECK(address_entry_child != NULL);\r
+  if (!address_entry_child) {\r
+    return;\r
+  }\r
+  Address child_addr = reinterpret_cast<Address>(address_entry_child->value);\r
+\r
+  (*individualReteiners)[child_addr].references_.insert(parent_ref_id);\r
+}\r
+\r
+\r
+void XDKSnapshotFiller::SetNamedAutoIndexReference(HeapGraphEdge::Type type,\r
+                                int parent,\r
+                                HeapEntry* child_entry) {\r
+}\r
+\r
+\r
+}\r
+}  // namespace v8::internal\r
diff --git a/src/v8/src/xdk-allocation.h b/src/v8/src/xdk-allocation.h
new file mode 100644 (file)
index 0000000..79384e9
--- /dev/null
@@ -0,0 +1,168 @@
+// Copyright 2014 the V8 project authors. All rights reserved.\r
+// Use of this source code is governed by a BSD-style license that can be\r
+// found in the LICENSE file.\r
+\r
+#ifndef V8_XDK_ALLOCATION_H_\r
+#define V8_XDK_ALLOCATION_H_\r
+\r
+#include <map>\r
+#include <string>\r
+#include "src/base/platform/time.h"\r
+\r
+namespace v8 {\r
+namespace internal {\r
+\r
+class HeapObjectsMap;\r
+class HeapEventXDK;\r
+class ClassNames;\r
+class ShadowStack;\r
+class SymbolsStorage;\r
+class AggregatedChunks;\r
+class RuntimeInfo;\r
+class References;\r
+class RefSet;\r
+\r
+\r
+class XDKSnapshotFiller: public SnapshotFiller {\r
+ public:\r
+  explicit XDKSnapshotFiller(HeapObjectsMap* heap_object_map,\r
+                             StringsStorage* names,\r
+                             XDKAllocationTracker* allocation_tracker)\r
+      : names_(names),\r
+      heap_object_map_(heap_object_map),\r
+      allocation_tracker_(allocation_tracker),\r
+      heap_entries_(HashMap::PointersMatch),\r
+      index_to_address_(HashMap::PointersMatch) {}\r
+  virtual ~XDKSnapshotFiller() {}\r
+\r
+  HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator);\r
+  HeapEntry* FindEntry(HeapThing thing);\r
+  HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator);\r
+  void SetIndexedReference(HeapGraphEdge::Type type,\r
+                           int parent,\r
+                           int index,\r
+                           HeapEntry* child_entry);\r
+  void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,\r
+                                    int parent,\r
+                                    HeapEntry* child_entry);\r
+  void SetNamedReference(HeapGraphEdge::Type type,\r
+                         int parent,\r
+                         const char* reference_name,\r
+                         HeapEntry* child_entry);\r
+  void SetNamedAutoIndexReference(HeapGraphEdge::Type type,\r
+                                  int parent,\r
+                                  HeapEntry* child_entry);\r
+\r
+ private:\r
+  StringsStorage* names_;\r
+  HeapObjectsMap* heap_object_map_;\r
+  XDKAllocationTracker* allocation_tracker_;\r
+  HashMap heap_entries_;\r
+  HashMap index_to_address_;\r
+\r
+\r
+  List<HeapEntry> heap_entries_list_;\r
+\r
+  HeapEntry* AddEntry(HeapThing thing,\r
+                      HeapObject* object,\r
+                      HeapEntry::Type type,\r
+                      const char* name);\r
+\r
+  static uint32_t Hash(HeapThing thing) {\r
+    return ComputeIntegerHash(\r
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),\r
+        v8::internal::kZeroHashSeed);\r
+  }\r
+  static uint32_t HashInt(int key) {\r
+    return ComputeIntegerHash(key, v8::internal::kZeroHashSeed);\r
+  }\r
+};\r
+\r
+\r
+class XDKAllocationTracker {\r
+ public:\r
+  XDKAllocationTracker(HeapProfiler* heap_profiler,\r
+                       HeapObjectsMap* ids,\r
+                       StringsStorage* names,\r
+                       int stackDepth,\r
+                       bool collectRetention,\r
+                       bool strict_collection);\r
+  ~XDKAllocationTracker();\r
+\r
+  void OnAlloc(Address addr, int size);\r
+  void OnMove(Address from, Address to, int size);\r
+  void CollectFreedObjects(bool bAll = false, bool initPreCollect = false);\r
+  HeapEventXDK* stopTracking();\r
+  OutputStream::WriteResult  SendChunk(OutputStream* stream);\r
+  unsigned GetTraceNodeId(Address address);\r
+  void clearIndividualReteiners();\r
+  std::map<Address, RefSet>* GetIndividualReteiners();\r
+\r
+  unsigned FindOrInitClassName(Address address, unsigned ts);\r
+\r
+ private:\r
+  static const int RETAINED_DELTA = 1000;\r
+\r
+  // external object\r
+  HeapProfiler* heap_profiler_;\r
+  HeapObjectsMap* ids_;\r
+  StringsStorage* names_;\r
+\r
+  AggregatedChunks* aggregated_chunks_;\r
+  RuntimeInfo* runtime_info_;\r
+  void SerializeChunk(std::string* symbols, std::string* types,\r
+                      std::string* frames, std::string* chunks,\r
+                      std::string* retentions, bool final = false);\r
+\r
+  unsigned FindClassName(Address address);\r
+  unsigned InitClassName(Address address, unsigned ts, unsigned size);\r
+\r
+  SymbolsStorage* symbols_;\r
+  ShadowStack* collectedStacks_;\r
+  ClassNames* classNames_;\r
+\r
+  unsigned outOfContextFrame_;\r
+  unsigned AllocatedBeforeCollectionFrame_;\r
+\r
+  v8::base::Time baseTime_;\r
+  unsigned latest_delta_;\r
+  unsigned int GetTimeDelta();\r
+\r
+  int stackDepth_;\r
+  bool collectRetention_;\r
+  bool strict_collection_;\r
+  References* references_;\r
+  std::map<Address, RefSet> individualReteiners_;\r
+};\r
+\r
+\r
+class HeapEventXDK {\r
+ public:\r
+  HeapEventXDK(unsigned int duration,\r
+               const std::string& symbols, const std::string& types,\r
+               const std::string& frames, const std::string& chunks,\r
+               const std::string& retentions) :\r
+    symbols_(symbols), types_(types), frames_(frames), chunks_(chunks),\r
+    duration_(duration), retentions_(retentions) {\r
+  }\r
+\r
+  unsigned int duration() const {return duration_; }\r
+  const char* symbols() const { return symbols_.c_str(); }\r
+  const char* types() const { return types_.c_str(); }\r
+  const char* frames() const { return frames_.c_str(); }\r
+  const char* chunks() const { return chunks_.c_str(); }\r
+  const char* retentions()  const { return retentions_.c_str(); }\r
+\r
+ private:\r
+  std::string symbols_;\r
+  std::string types_;\r
+  std::string frames_;\r
+  std::string chunks_;\r
+  unsigned int duration_;\r
+  std::string retentions_;\r
+  DISALLOW_COPY_AND_ASSIGN(HeapEventXDK);\r
+};\r
+\r
+} }  // namespace v8::internal\r
+\r
+#endif  // V8_XDK_ALLOCATION_H_\r
diff --git a/src/v8/src/xdk-utils.cc b/src/v8/src/xdk-utils.cc
new file mode 100644 (file)
index 0000000..b17eb95
--- /dev/null
@@ -0,0 +1,541 @@
+// Copyright 2014 the V8 project authors. All rights reserved.\r
+// Use of this source code is governed by a BSD-style license that can be\r
+// found in the LICENSE file.\r
+\r
+#include "src/v8.h"\r
+\r
+#include "src/frames-inl.h"\r
+#include "src/xdk-utils.h"\r
+\r
+namespace v8 {\r
+namespace internal {\r
+\r
+static bool AddressesMatch(void* key1, void* key2) {\r
+  return key1 == key2;\r
+}\r
+\r
+\r
+static uint32_t CharAddressHash(char* addr) {\r
+  return ComputeIntegerHash(static_cast<uint32_t>(\r
+      reinterpret_cast<uintptr_t>(addr)),\r
+      v8::internal::kZeroHashSeed);\r
+}\r
+\r
+\r
+static uint32_t AddressHash(Address addr) {\r
+  return ComputeIntegerHash(static_cast<uint32_t>(\r
+      reinterpret_cast<uintptr_t>(addr)),\r
+      v8::internal::kZeroHashSeed);\r
+}\r
+\r
+\r
+ClassNames::ClassNames(StringsStorage* names)\r
+    : counter_(0),\r
+    char_to_idx_(AddressesMatch),\r
+    names_(names) {\r
+}\r
+\r
+\r
+unsigned ClassNames::registerName(const char* name) {\r
+  // since const char is retained outside and cannot be moved, we rely on this\r
+  // and just compare the pointers. It should be enough for the strings from the\r
+  // only one StringStorage\r
+  unsigned counter;\r
+  HashMap::Entry* entry = char_to_idx_.Lookup(const_cast<char*>(name),\r
+      CharAddressHash(const_cast<char*>(name)),\r
+      true);\r
+  if (entry->value == NULL) {\r
+    counter = ++counter_;\r
+    entry->value = reinterpret_cast<void*>(counter);\r
+  } else {\r
+    counter = static_cast<unsigned>(reinterpret_cast<uintptr_t>(entry->value));\r
+  }\r
+  return counter;\r
+}\r
+\r
+\r
+std::string ClassNames::SerializeChunk() {\r
+  std::stringstream serialized;\r
+  for (HashMap::Entry* p = char_to_idx_.Start(); p != NULL;\r
+      p = char_to_idx_.Next(p)) {\r
+    serialized << static_cast<unsigned>(\r
+        reinterpret_cast<uintptr_t>(p->value)) << "," <<\r
+        reinterpret_cast<char*>(p->key) << std::endl;\r
+  }\r
+\r
+  return serialized.str();\r
+}\r
+\r
+\r
+String* ClassNames::GetConstructorName(Address address) {\r
+  HeapObject *heap_object = HeapObject::FromAddress(address);\r
+  bool is_js_object = heap_object->IsJSObject();\r
+  if (!is_js_object) {\r
+    // TODO(amalyshe): look for another function for taking the class name\r
+    // String* constructor_name = object2->constructor_name();\r
+    return NULL;\r
+  }\r
+  JSObject* object = JSObject::cast(heap_object);\r
+  Heap* heap = object->GetHeap();\r
+  if (object->IsJSFunction()) return heap->closure_string();\r
+  return object->constructor_name();\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+ShadowStack::ShadowStack() {\r
+  last_index_ = 1;\r
+  serializedCounter_ = last_index_;\r
+  root_.index_ = 0;\r
+  root_.parent_ = NULL;\r
+  root_.callsite_ = 0;\r
+}\r
+\r
+\r
+ShadowStack::~ShadowStack() {\r
+  // erasing all objects from the current container\r
+  std::map<unsigned, CallTree*>::iterator eit = allNodes_.begin();\r
+  while (eit != allNodes_.end()) {\r
+    delete eit->second;\r
+    eit++;\r
+  }\r
+}\r
+\r
+\r
+unsigned ShadowStack::registerStack(const List<unsigned>& shadow_stack_) {\r
+    // look for the latest node\r
+    CallTree* pNode = &root_;\r
+    // go over all entries and add them to the tree if they are not in the map\r
+    int i, j;\r
+    for (i = shadow_stack_.length()-1; i != -1; i--) {\r
+      std::map<unsigned, CallTree*>::iterator it =\r
+          pNode->children_.find(shadow_stack_[i]);\r
+      if (it == pNode->children_.end())\r
+          break;\r
+      pNode = it->second;\r
+    }\r
+    // verification if we need to add something or not\r
+    for (j = i; j != -1; j--) {\r
+      CallTree* pNodeTmp = new CallTree;\r
+      pNodeTmp->index_ = last_index_++;\r
+      pNodeTmp->parent_ = pNode;\r
+      pNodeTmp->callsite_ = shadow_stack_[j];\r
+      pNode->children_[shadow_stack_[j]] = pNodeTmp;\r
+      allNodes_[pNodeTmp->index_] = pNodeTmp;\r
+      pNode = pNodeTmp;\r
+    }\r
+    return pNode->index_;\r
+}\r
+\r
+\r
+std::string ShadowStack::SerializeChunk() {\r
+  std::stringstream str;\r
+  std::map<unsigned, CallTree*>::iterator it =\r
+      allNodes_.find(serializedCounter_);\r
+  while (it!= allNodes_.end()) {\r
+    str << it->first << "," << it->second->callsite_ << "," <<\r
+        it->second->parent_->index_ << std::endl;\r
+    it++;\r
+  }\r
+\r
+  serializedCounter_ = last_index_;\r
+  return str.str();\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+static bool SymInfoMatch(void* key1, void* key2) {\r
+  SymInfoKey* key_c1 = reinterpret_cast<SymInfoKey*>(key1);\r
+  SymInfoKey* key_c2 = reinterpret_cast<SymInfoKey*>(key2);\r
+  return *key_c1 == *key_c2;\r
+}\r
+\r
+\r
+static uint32_t SymInfoHash(const SymInfoKey& key) {\r
+  uint32_t hash = 0;\r
+  // take the low 16 bits of function_id_\r
+  hash |= (key.function_id_ & 0xffff);\r
+  // take the low 8 bits of line_ and column_ and init highest bits\r
+  hash |= ((key.line_ & 0xff) << 16);\r
+  hash |= ((key.column_ & 0xff) << 14);\r
+\r
+  return hash;\r
+}\r
+\r
+\r
+struct SymbolCached {\r
+  unsigned int symbol_id_;\r
+  uintptr_t function_;\r
+};\r
+\r
+\r
+SymbolsStorage::SymbolsStorage(Heap* heap, StringsStorage* names) :\r
+  symbols_(SymInfoMatch),\r
+  curSym_(1),\r
+  sym_info_hash_(AddressesMatch),\r
+  heap_(heap),\r
+  names_(names) {\r
+  reserved_key_ = new SymInfoKey();\r
+}\r
+\r
+\r
+SymbolsStorage::~SymbolsStorage() {\r
+  // go over map and delete all keys and values\r
+  for (HashMap::Entry* p = symbols_.Start(); p != NULL; p = symbols_.Next(p)) {\r
+    delete reinterpret_cast<SymInfoValue*>(p->value);\r
+    delete reinterpret_cast<SymInfoKey*>(p->key);\r
+  }\r
+  delete reserved_key_;\r
+}\r
+\r
+\r
+unsigned SymbolsStorage::registerSymInfo(size_t functionId,\r
+                                         std::string functionName,\r
+                                         std::string sourceName,\r
+                                         unsigned line,\r
+                                         unsigned column) {\r
+  if (sourceName.empty()) {\r
+    sourceName = "unknown";\r
+  }\r
+\r
+  reserved_key_->function_id_ = functionId;\r
+  reserved_key_->line_ = line;\r
+  reserved_key_->column_ = column;\r
+\r
+  HashMap::Entry* entry = symbols_.Lookup(reserved_key_,\r
+                                          SymInfoHash(*reserved_key_), true);\r
+  if (entry->value) {\r
+    return reinterpret_cast<SymInfoValue*>(entry->value)->symId_;\r
+  }\r
+\r
+  // else initialize by new one\r
+  SymInfoValue* value = new SymInfoValue;\r
+  value->symId_ = curSym_++;\r
+  value->funcName_ = functionName;\r
+  value->sourceFile_ = sourceName;\r
+  entry->value = value;\r
+\r
+  // compensation for registered one\r
+  reserved_key_ = new SymInfoKey();\r
+\r
+  return value->symId_;\r
+}\r
+\r
+\r
+std::string SymbolsStorage::SerializeChunk() {\r
+  std::stringstream serialized;\r
+  for (HashMap::Entry* p = symbols_.Start(); p != NULL; p = symbols_.Next(p)) {\r
+    SymInfoValue* v = reinterpret_cast<SymInfoValue*>(p->value);\r
+    SymInfoKey* k = reinterpret_cast<SymInfoKey*>(p->key);\r
+    serialized << v->symId_ << "," << k->function_id_ << "," <<\r
+        v->funcName_ << "," << v->sourceFile_ << "," <<\r
+        k->line_ << "," << k->column_ << std::endl;\r
+  }\r
+\r
+  return serialized.str();\r
+}\r
+\r
+\r
+unsigned SymbolsStorage::FindOrRegisterFrame(JavaScriptFrame* frame) {\r
+  SharedFunctionInfo *shared = frame->function()->shared();\r
+  DCHECK(shared);\r
+  Isolate *isolate = heap_->isolate();\r
+\r
+  Address pc = frame->pc();\r
+  unsigned int symbolId = 0;\r
+\r
+  // We don't rely on the address only. Since this is JIT based language,\r
+  // the address might be occupied by other function\r
+  // thus we are verifying if the same function takes this place\r
+  // before we take symbol info from the cache\r
+  HashMap::Entry* sym_entry = sym_info_hash_.Lookup(\r
+          reinterpret_cast<void*>(pc), AddressHash(pc), true);\r
+  if (sym_entry->value == NULL ||\r
+      (reinterpret_cast<SymbolCached*>(sym_entry->value)->function_ !=\r
+        reinterpret_cast<uintptr_t>(frame->function()))) {\r
+    if (sym_entry->value) {\r
+      delete reinterpret_cast<SymbolCached*>(sym_entry->value);\r
+    }\r
+\r
+    const char *s = names_->GetFunctionName(shared->DebugName());\r
+    // trying to get the source name and line#\r
+    Code *code = Code::cast(isolate->FindCodeObject(pc));\r
+    if (code) {\r
+      int source_pos = code->SourcePosition(pc);\r
+      Object *maybe_script = shared->script();\r
+      if (maybe_script && maybe_script->IsScript()) {\r
+        Handle<Script> script(Script::cast(maybe_script));\r
+        if (!script.is_null()) {\r
+          int line = script->GetLineNumber(source_pos) + 1;\r
+          // TODO(amalyshe): check if this can be used:\r
+          // int line = GetScriptLineNumberSafe(script, source_pos) + 1;\r
+          // TODO(amalyshe): add column number getting\r
+          int column = 0;  // GetScriptColumnNumber(script, source_pos);\r
+          Object *script_name_raw = script->name();\r
+          if (script_name_raw->IsString()) {\r
+            String *script_name = String::cast(script->name());\r
+            SmartArrayPointer<char> c_script_name =\r
+              script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);\r
+            symbolId = registerSymInfo((size_t)frame->function(), s,\r
+                                       c_script_name.get(), line, column);\r
+          }\r
+        }\r
+      }\r
+    }\r
+    if (symbolId == 0) {\r
+      symbolId = registerSymInfo((size_t)frame->function(), s, "", 0, 0);\r
+    }\r
+\r
+    SymbolCached* symCached = new SymbolCached;\r
+    symCached->function_ = reinterpret_cast<uintptr_t>(frame->function());\r
+    symCached->symbol_id_ = symbolId;\r
+    sym_entry->value = symCached;\r
+  } else {\r
+    symbolId = reinterpret_cast<SymbolCached*>(sym_entry->value)->symbol_id_;\r
+  }\r
+  return symbolId;\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+RuntimeInfo::RuntimeInfo(AggregatedChunks* aggregated_chunks):\r
+  working_set_hash_(AddressesMatch),\r
+  aggregated_chunks_(aggregated_chunks),\r
+  AllocatedBeforeCollectionFrame_(0) {\r
+}\r
+\r
+\r
+PostCollectedInfo* RuntimeInfo::FindPostCollectedInfo(Address addr) {\r
+  HashMap::Entry* entry = working_set_hash_.Lookup(\r
+          reinterpret_cast<void*>(addr), AddressHash(addr), false);\r
+  if (entry && entry->value) {\r
+    PostCollectedInfo* info =\r
+        reinterpret_cast<PostCollectedInfo*>(entry->value);\r
+    return info;\r
+  }\r
+  return NULL;\r
+}\r
+\r
+\r
+PostCollectedInfo* RuntimeInfo::AddPostCollectedInfo(Address addr,\r
+                                                    unsigned time_delta,\r
+                                                    PostCollectedInfo* info) {\r
+  PostCollectedInfo* info_new = NULL;\r
+  if (!info) {\r
+    info_new = new PostCollectedInfo;\r
+  } else {\r
+    info_new = info;\r
+  }\r
+\r
+  HashMap::Entry* entry = working_set_hash_.Lookup(\r
+          reinterpret_cast<void*>(addr), AddressHash(addr), true);\r
+  DCHECK(entry);\r
+  if (entry->value != NULL) {\r
+    // compensation of the wrong deallocation place\r
+    // we were not able to work the GC epilogue callback because GC is not\r
+    // iteratable in the prologue\r
+    // thus we need to mark the object as freed\r
+    PostCollectedInfo* info_old =\r
+        static_cast<PostCollectedInfo*>(entry->value);\r
+    aggregated_chunks_->addObjectToAggregated(info_old, time_delta);\r
+    delete info_old;\r
+  }\r
+\r
+  entry->value = info_new;\r
+  return info_new;\r
+}\r
+\r
+\r
+PostCollectedInfo* RuntimeInfo::AddPreCollectionInfo(Address addr,\r
+                                                     unsigned size) {\r
+  PostCollectedInfo* info = AddPostCollectedInfo(addr);\r
+  info->size_ = size;\r
+  info->timeStamp_ = 0;\r
+  info->stackId_ = AllocatedBeforeCollectionFrame_;\r
+  info->className_ = (unsigned)-1;\r
+  return info;\r
+}\r
+\r
+\r
+void RuntimeInfo::RemoveInfo(Address addr) {\r
+  working_set_hash_.Remove(reinterpret_cast<void*>(addr), AddressHash(addr));\r
+}\r
+\r
+\r
+void RuntimeInfo::InitABCFrame(unsigned abc_frame) {\r
+  AllocatedBeforeCollectionFrame_ = abc_frame;\r
+}\r
+\r
+\r
+void RuntimeInfo::CollectGarbaged(unsigned ts) {\r
+  // iteration over the working_set_hash_\r
+  for (HashMap::Entry* p = working_set_hash_.Start(); p != NULL;\r
+      p = working_set_hash_.Next(p)) {\r
+    if (p->value) {\r
+      PostCollectedInfo* info = static_cast<PostCollectedInfo*>(p->value);\r
+      if (info->dirty_ == false) {\r
+        // need to care of allocated during collection.\r
+        // if timeStamp_ == 0 this object was allocated before collection\r
+        // and we don't care of it\r
+        aggregated_chunks_->addObjectToAggregated(info, ts);\r
+        delete info;\r
+        p->value = NULL;\r
+      } else {\r
+        info->dirty_ = false;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+\r
+//------------------------------------------------------------------------------\r
+static bool AggregatedMatch(void* key1, void* key2) {\r
+  // cast to the AggregatedKey\r
+  AggregatedKey* key_c1 = reinterpret_cast<AggregatedKey*>(key1);\r
+  AggregatedKey* key_c2 = reinterpret_cast<AggregatedKey*>(key2);\r
+  return *key_c1 == *key_c2;\r
+}\r
+\r
+\r
+static uint32_t AggregatedHash(const AggregatedKey& key) {\r
+  uint32_t hash = 0;\r
+  // take the low 8 bits of stackId_\r
+  hash |= (key.stackId_ & 0xff);\r
+  // take the low 8 bits of classId_ and init hash from 8th to 15th bits\r
+  hash |= ((key.classId_ & 0xff) << 8);\r
+  // since times are well graduated it's no sense take the lowest 8 bit\r
+  // instead this we will move to 3 bits and only then take 8 bits\r
+  hash |= (((key.tsBegin_ >> 3) & 0xff) << 16);\r
+  hash |= (((key.tsBegin_ >> 3) & 0xff) << 24);\r
+  return hash;\r
+}\r
+\r
+\r
+AggregatedChunks::AggregatedChunks() :\r
+  aggregated_map_(AggregatedMatch),\r
+  bucketSize_(500) {\r
+  reserved_key_ = new AggregatedKey();\r
+}\r
+\r
+\r
+AggregatedChunks::~AggregatedChunks() {\r
+  delete reserved_key_;\r
+}\r
+\r
+\r
+void AggregatedChunks::addObjectToAggregated(PostCollectedInfo* info,\r
+                                                        unsigned td) {\r
+  reserved_key_->stackId_ = info->stackId_;\r
+  reserved_key_->classId_ = info->className_;\r
+  // get the bucket for the first time\r
+  reserved_key_->tsBegin_ = info->timeStamp_ - (info->timeStamp_ % bucketSize_);\r
+  reserved_key_->tsEnd_ = td - (td % bucketSize_);\r
+\r
+  HashMap::Entry* aggregated_entry = aggregated_map_.Lookup(reserved_key_,\r
+                                                AggregatedHash(*reserved_key_),\r
+                                                true);\r
+  if (aggregated_entry->value) {\r
+    // no need to store the latest record in the aggregated_keys_list_\r
+    AggregatedValue* value =\r
+                reinterpret_cast<AggregatedValue*>(aggregated_entry->value);\r
+    value->objects_++;\r
+    value->size_ += info->size_;\r
+  } else {\r
+    reserved_key_ = new AggregatedKey;\r
+    AggregatedValue* value = new AggregatedValue;\r
+    value->objects_ = 1;\r
+    value->size_ = info->size_;\r
+    aggregated_entry->value = value;\r
+  }\r
+}\r
+\r
+\r
+std::string AggregatedChunks::SerializeChunk() {\r
+  std::stringstream schunks;\r
+  for (HashMap::Entry* p = aggregated_map_.Start(); p != NULL;\r
+      p = aggregated_map_.Next(p)) {\r
+    if (p->key && p->value) {\r
+      AggregatedKey* key = reinterpret_cast<AggregatedKey*>(p->key);\r
+      AggregatedValue* value = reinterpret_cast<AggregatedValue*>(p->value);\r
+      schunks <<\r
+        key->tsBegin_ << "," << key->tsEnd_ << "," <<\r
+        key->stackId_ << "," << key->classId_ << "," <<\r
+        value->size_ << "," << value->objects_ << std::endl;\r
+      delete key;\r
+      delete value;\r
+    }\r
+  }\r
+\r
+  aggregated_map_.Clear();\r
+\r
+  return schunks.str();\r
+}\r
+\r
+\r
+// -----------------------------------------------------------------------------\r
+void References::addReference(const RefId& parent, const RefSet& refSet,\r
+                               int parentTime) {\r
+  // looking for the parent in the refMap_\r
+  PARENTREFMAP::iterator cit = refMap_.find(parent);\r
+  if (cit != refMap_.end()) {\r
+    REFERENCESETS& sets = cit->second;\r
+    REFERENCESETS::iterator it = sets.find(refSet);\r
+    if (it != sets.end()) {\r
+      // look for the time\r
+      TIMETOCOUNT::iterator cittc = it->second.find(parentTime);\r
+      if (cittc != it->second.end()) {\r
+        cittc->second++;\r
+      } else {\r
+        it->second[parentTime] = 1;\r
+      }\r
+    } else {\r
+      TIMETOCOUNT tc;\r
+      tc[parentTime] = 1;\r
+      sets[refSet] = tc;\r
+    }\r
+  } else {\r
+    // adding new parent, new sets\r
+    REFERENCESETS sets;\r
+    TIMETOCOUNT tc;\r
+    tc[parentTime] = 1;\r
+    sets[refSet] = tc;\r
+    refMap_[parent] = sets;\r
+  }\r
+}\r
+\r
+\r
+void References::clear() {\r
+  refMap_.clear();\r
+}\r
+\r
+\r
+std::string References::serialize() const {\r
+  std::stringstream str;\r
+  PARENTREFMAP::const_iterator citrefs = refMap_.begin();\r
+  while (citrefs != refMap_.end()) {\r
+    REFERENCESETS::const_iterator citsets = citrefs->second.begin();\r
+    while (citsets != citrefs->second.end()) {\r
+      str << citrefs->first.stackId_ << "," << citrefs->first.classId_;\r
+      // output of length, and content of TIMETOCOUNT\r
+      str << "," << citsets->second.size();\r
+      TIMETOCOUNT::const_iterator cittc = citsets->second.begin();\r
+      while (cittc != citsets->second.end()) {\r
+        str << "," << cittc->first << "," << cittc->second;\r
+        cittc++;\r
+      }\r
+      REFERENCESET::const_iterator citset = citsets->first.references_.begin();\r
+      while (citset != citsets->first.references_.end()) {\r
+        str << "," << citset->stackId_ << "," << citset->classId_<< "," <<\r
+          citset->field_;\r
+        citset++;\r
+      }\r
+      str << std::endl;\r
+      citsets++;\r
+    }\r
+    citrefs++;\r
+  }\r
+  return str.str();\r
+}\r
+\r
+\r
+} }  // namespace v8::internal\r
diff --git a/src/v8/src/xdk-utils.h b/src/v8/src/xdk-utils.h
new file mode 100644 (file)
index 0000000..b076481
--- /dev/null
@@ -0,0 +1,249 @@
+// Copyright 2014 the V8 project authors. All rights reserved.\r
+// Use of this source code is governed by a BSD-style license that can be\r
+// found in the LICENSE file.\r
+\r
+#ifndef __xdk_utils_h__\r
+#define __xdk_utils_h__\r
+\r
+#include <map>\r
+#include <set>\r
+#include <sstream>\r
+#include <string>\r
+#include "src/hashmap.h"\r
+\r
+namespace v8 {\r
+namespace internal {\r
+\r
+class AggregatedChunks;\r
+class StringsStorage;\r
+class JavaScriptFrame;\r
+\r
+// --- ClassNames\r
+class ClassNames {\r
+ public:\r
+  explicit ClassNames(StringsStorage* names);\r
+\r
+  unsigned registerName(const char* className);\r
+  std::string SerializeChunk();\r
+  String* GetConstructorName(Address address);\r
+\r
+ private:\r
+  unsigned counter_;\r
+  HashMap char_to_idx_;\r
+  StringsStorage* names_;\r
+};\r
+\r
+\r
+// --- ShadowStack\r
+class CallTree {\r
+ public:\r
+  // For quick search we use below member. it is not reasnable to use here\r
+  // map because it occupies a lot of space even in empty state and such nodes\r
+  // will be many. In opposite to map, std::map uses binary tree search and\r
+  // don't store buffer, but allocates it dinamically\r
+  std::map<unsigned, CallTree*> children_;\r
+\r
+  // This is _not_ the same as index in the children_. This index is\r
+  // incremental value from list of all nodes, but the key in the children_ is\r
+  // callsite\r
+  unsigned index_;\r
+  CallTree* parent_;\r
+  // the only one field which characterize the call point\r
+  unsigned callsite_;\r
+};\r
+\r
+\r
+class ShadowStack {\r
+  CallTree root_;\r
+\r
+  // unsigned here is ok, size_t is not required because even 10 millions\r
+  // objects in this class will lead to the significant memory consumption\r
+  unsigned last_index_;\r
+\r
+  // TODO(amalyshe): rewrite using List, storing nodes and use index in the list\r
+  // instead pointer to CallTree in the children_\r
+  std::map<unsigned, CallTree*> allNodes_;\r
+  unsigned serializedCounter_;\r
+ public:\r
+  ShadowStack();\r
+  ~ShadowStack();\r
+  // Returns unique stack id. This method can work with incremental stacks when\r
+  // we have old stack id, new tail and number of functions that we need to\r
+  // unroll.\r
+  unsigned registerStack(const List<unsigned>& shadow_stack_);\r
+  std::string SerializeChunk();\r
+};\r
+\r
+\r
+// --- SymbolsStorage\r
+struct SymInfoKey {\r
+  size_t function_id_;\r
+  unsigned line_;\r
+  unsigned column_;\r
+};\r
+\r
+bool inline operator == (const SymInfoKey& key1, const SymInfoKey& key2) {\r
+  return key1.function_id_ == key2.function_id_ &&\r
+    key1.line_ == key2.line_ &&\r
+    key1.column_ == key2.column_;\r
+}\r
+\r
+\r
+struct SymInfoValue {\r
+  unsigned symId_;\r
+  std::string funcName_;\r
+  std::string sourceFile_;\r
+};\r
+\r
+\r
+class SymbolsStorage {\r
+ public:\r
+  unsigned registerSymInfo(size_t functionId,\r
+                               std::string functionName,\r
+                               std::string sourceName, unsigned line,\r
+                               unsigned column);\r
+  unsigned FindOrRegisterFrame(JavaScriptFrame* frame);\r
+  SymbolsStorage(Heap* heap, StringsStorage* names);\r
+  ~SymbolsStorage();\r
+  std::string SerializeChunk();\r
+\r
+ private:\r
+  HashMap symbols_;\r
+  unsigned curSym_;\r
+  // fast living storage which duplicate info but is cleaned regularly\r
+  SymInfoKey* reserved_key_;\r
+  HashMap sym_info_hash_;\r
+  Heap* heap_;\r
+  StringsStorage* names_;\r
+};\r
+\r
+\r
+struct PostCollectedInfo {\r
+  int size_;\r
+  int timeStamp_;\r
+  int stackId_;\r
+  unsigned className_;\r
+  bool dirty_;\r
+};\r
+\r
+\r
+class RuntimeInfo {\r
+ public:\r
+  explicit RuntimeInfo(AggregatedChunks* aggregated_chunks);\r
+  PostCollectedInfo* FindPostCollectedInfo(Address addr);\r
+  PostCollectedInfo* AddPostCollectedInfo(Address addr,\r
+                                          unsigned time_delta = 0,\r
+                                          PostCollectedInfo* info = NULL);\r
+  PostCollectedInfo* AddPreCollectionInfo(Address addr, unsigned size);\r
+  void RemoveInfo(Address addr);\r
+  void InitABCFrame(unsigned abc_frame);\r
+  void CollectGarbaged(unsigned ts);\r
+\r
+ private:\r
+  HashMap working_set_hash_;\r
+  AggregatedChunks* aggregated_chunks_;\r
+  unsigned AllocatedBeforeCollectionFrame_;\r
+};\r
+\r
+\r
+struct AggregatedKey {\r
+  int stackId_;\r
+  // do we need class here? is not it defined by the stack id?\r
+  unsigned classId_;\r
+  unsigned tsBegin_;\r
+  unsigned tsEnd_;\r
+};\r
+\r
+bool inline operator == (const AggregatedKey& key1, const AggregatedKey& key2) {\r
+  return key1.stackId_ == key2.stackId_ &&\r
+    key1.classId_ == key2.classId_ &&\r
+    key1.tsBegin_ == key2.tsBegin_ &&\r
+    key1.tsEnd_ == key2.tsEnd_;\r
+}\r
+\r
+\r
+struct AggregatedValue {\r
+  unsigned size_;\r
+  unsigned objects_;\r
+};\r
+\r
+\r
+class AggregatedChunks {\r
+ public:\r
+  AggregatedChunks();\r
+  ~AggregatedChunks();\r
+  void addObjectToAggregated(PostCollectedInfo* info, unsigned td);\r
+  std::string SerializeChunk();\r
+\r
+ private:\r
+  HashMap aggregated_map_;\r
+  int bucketSize_;\r
+  AggregatedKey* reserved_key_;\r
+};\r
+\r
+\r
+struct RefId {\r
+  int stackId_;\r
+  int classId_;\r
+  std::string field_;\r
+};\r
+\r
+inline bool operator < (const RefId& first, const RefId& second ) {\r
+  if (first.stackId_ < second.stackId_ )\r
+    return true;\r
+  else if (first.stackId_ > second.stackId_ )\r
+    return false;\r
+  if (first.classId_ < second.classId_ )\r
+    return true;\r
+  if (first.classId_ > second.classId_ )\r
+    return false;\r
+  if (first.field_.compare(second.field_) < 0 )\r
+    return true;\r
+\r
+  return false;\r
+}\r
+\r
+typedef std::set<RefId> REFERENCESET;\r
+\r
+\r
+struct RefSet {\r
+  REFERENCESET references_;\r
+};\r
+\r
+inline bool operator < (const RefSet& first, const RefSet& second) {\r
+  // compare the sizes first of all\r
+  if (first.references_.size() != second.references_.size() )\r
+    return first.references_.size() < second.references_.size();\r
+  // iterating by the first\r
+  REFERENCESET::const_iterator cit1 = first.references_.begin();\r
+  REFERENCESET::const_iterator cit2 = second.references_.begin();\r
+  while (cit1 != first.references_.end()) {\r
+    if (*cit1 < *cit2 )\r
+      return true;\r
+    if (*cit2 < *cit1 )\r
+      return false;\r
+    cit1++;\r
+    cit2++;\r
+  }\r
+  return false;\r
+}\r
+typedef std::map<unsigned int, int> TIMETOCOUNT;\r
+typedef std::map<RefSet, TIMETOCOUNT> REFERENCESETS;\r
+typedef std::map<RefId, REFERENCESETS> PARENTREFMAP;\r
+\r
+\r
+class References {\r
+ public:\r
+  void addReference(const RefId& parent,\r
+                    const RefSet& refSet,\r
+                    int parentTime);\r
+  void clear();\r
+  std::string serialize() const;\r
+\r
+ private:\r
+  PARENTREFMAP refMap_;\r
+};\r
+\r
+\r
+} }  // namespace v8::internal\r
+#endif  // __xdk_utils_h__\r
index b00e87d..bc955cd 100644 (file)
@@ -1068,6 +1068,7 @@ TEST(BoundFunctionCall) {
 TEST(TickLines) {
   CcTest::InitializeVM();
   LocalContext env;
+  i::FLAG_turbo_source_positions = true;
   i::Isolate* isolate = CcTest::i_isolate();
   i::Factory* factory = isolate->factory();
   i::HandleScope scope(isolate);
@@ -1077,13 +1078,11 @@ TEST(TickLines) {
   const char* func_name = "func";
   i::SNPrintF(script,
       "function %s() {\n"
-      "  for (var i = 0; i < 10; ++i) {\n"
-      "    var n = 0;\n"
-      "    var m = 100*100;\n"
-      "    while (m > 1) {\n"
-      "      m--;\n"
-      "      n += m * m * m;\n"
-      "    }\n"
+      "  var n = 0;\n"
+      "  var m = 100*100;\n"
+      "  while (m > 1) {\n"
+      "    m--;\n"
+      "    n += m * m * m;\n"
       "  }\n"
       "}\n"
       "%s();\n", func_name, func_name);
@@ -1103,7 +1102,7 @@ TEST(TickLines) {
     code = func->shared()->code();
   }
   CHECK_NE(NULL, code);
-  i::Address code_address = code->address();
+  i::Address code_address = code->instruction_start();
   CHECK_NE(NULL, code_address);
 
   CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
@@ -1140,7 +1139,7 @@ TEST(TickLines) {
   CHECK_EQ(func_name, func_entry->name());
   const i::JITLineInfoTable* line_info = func_entry->line_info();
   CHECK_NE(NULL, line_info);
-  CHECK_EQ(false, line_info->Empty());
+  CHECK(!line_info->empty());
 
   // Check the hit source lines using V8 Public APIs.
   const i::ProfileTree* tree = profile->top_down();
@@ -1158,7 +1157,7 @@ TEST(TickLines) {
   unsigned int line_count = func_node->GetHitLineCount();
   CHECK_EQ(2, line_count);  // Expect two hit source lines - #1 and #5.
   ScopedVector<v8::CpuProfileNode::LineTick> entries(line_count);
-  CHECK_EQ(true, func_node->GetLineTicks(&entries[0], line_count));
+  CHECK(func_node->GetLineTicks(&entries[0], line_count));
   int value = 0;
   for (int i = 0; i < entries.length(); i++)
     if (entries[i].line == hit_line) {
index 8f9b484..6842b1d 100644 (file)
@@ -38,6 +38,7 @@
 #include "src/heap-profiler.h"
 #include "src/snapshot.h"
 #include "src/utils-inl.h"
+#include "src/xdk-utils.h"
 #include "test/cctest/cctest.h"
 
 using i::AllocationTraceNode;
@@ -2804,3 +2805,375 @@ TEST(AddressToTraceMap) {
   CHECK_EQ(0, static_cast<int>(map.size()));
   CHECK_EQ(0, map.GetTraceNodeId(ToAddress(0x400)));
 }
+
+struct TestObjectInfo {
+  std::vector<std::string> bu_call_stack_;
+  std::string type_;
+  unsigned number_of_objects_;
+};
+
+struct TestFrameInfo {
+  unsigned frame_id_;
+  unsigned callsite_;
+  unsigned parent_;
+};
+
+struct Chunk {
+  unsigned time_begin_;
+  unsigned time_end_;
+  unsigned frame_id_;
+  unsigned type_id_;
+  unsigned size_;
+  unsigned number_of_objects_;
+};
+
+class XDKHPOutputChecker {
+ public:
+  // If info.number_of_objects_ is not eq 0, then it participates in the search
+  // and we look for the record by 3 parameters. In other case we look for the
+  // chunk by call stack and type id only
+  bool checkObjectsExists(const TestObjectInfo& info, std::string chunk) {
+    std::vector<Chunk> chunks = parseChunk(chunk);
+    // look for the frame id, which correspond to the passed stack
+    // get the type id:
+    std::vector<unsigned> frames = findFrame(info.bu_call_stack_);
+    unsigned type_id = types_[info.type_];
+    for (size_t i = 0; i < chunks.size(); i++) {
+      for (size_t j = 0; j < frames.size(); j++) {
+        if (chunks[i].frame_id_ == frames[j] && chunks[i].type_id_ == type_id &&
+            (info.number_of_objects_ ? chunks[i].number_of_objects_ ==
+            info.number_of_objects_ : true)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+  void parse(const char* symbols, const char* frames, const char* types) {
+    std::string symbols_std_ = symbols;
+    std::string frames_std_ = frames;
+    std::string types_std_ = types;
+    {
+      // parse symbols, don't care of line and column
+      size_t s1_pos = 0, s2_pos = 0;
+      int sym_id;
+      std::string function_name;
+      while (s2_pos != symbols_std_.npos) {
+        // look for the \n symbol
+        // format: symId, funcId, funcName, line, column
+        s2_pos = symbols_std_.find("\n", s1_pos);
+        if (s2_pos != symbols_std_.npos) {
+          int sym_id_e = symbols_std_.find(",", s1_pos);
+          std::string sym_id_s = symbols_std_.substr(s1_pos, sym_id_e - s1_pos);
+          sym_id = atoi(sym_id_s.c_str());
+          int func_id_e = symbols_std_.find(",", sym_id_e + 1);
+          int finc_name_e = symbols_std_.find(",", func_id_e + 1);
+          function_name = symbols_std_.substr(func_id_e + 1, finc_name_e -
+              func_id_e - 1);
+          symbols_[function_name] = sym_id;
+          s1_pos = s2_pos + 1;
+        }
+      }
+    }
+    {
+      // parse types
+      size_t s1_pos = 0, s2_pos = 0;
+      unsigned type_id;
+      std::string type_name;
+      while (s2_pos != types_std_.npos) {
+        // look for the \n symbol
+        // format: typeId, typeName
+        s2_pos = types_std_.find("\n", s1_pos);
+        if (s2_pos != types_std_.npos) {
+          int type_id_e = types_std_.find(",", s1_pos);
+          std::string sym_id_s = types_std_.substr(s1_pos, type_id_e - s1_pos);
+          type_id = atoi(sym_id_s.c_str());
+          type_name = types_std_.substr(type_id_e + 1, s2_pos - type_id_e - 1);
+
+          types_[type_name] = type_id;
+          s1_pos = s2_pos + 1;
+        }
+      }
+    }
+    {
+      // parse frames
+      size_t s1_pos = 0, s2_pos = 0;
+      int frame_id, symbol_id, parent_id;
+      while (s2_pos != frames_std_.npos) {
+        // look for the \n symbol
+        // format: frameId, symbolId, parentId
+        s2_pos = frames_std_.find("\n", s1_pos);
+        if (s2_pos != frames_std_.npos) {
+          int frame_id_e = frames_std_.find(",", s1_pos);
+          std::string frame_id_s = frames_std_.substr(s1_pos,
+                                                      frame_id_e - s1_pos);
+          frame_id = atoi(frame_id_s.c_str());
+
+          int symb_id_e = frames_std_.find(",", frame_id_e + 1);
+          std::string symb_id_s = frames_std_.substr(frame_id_e + 1,
+                                                    symb_id_e - frame_id_e - 1);
+          symbol_id = atoi(symb_id_s.c_str());
+
+          int parent_id_e = frames_std_.find(",", symb_id_e + 1);
+          std::string parent_id_s = frames_std_.substr(symb_id_e + 1,
+                                                      s2_pos - parent_id_e - 1);
+          parent_id = atoi(parent_id_s.c_str());
+          TestFrameInfo info;
+          info.callsite_ = symbol_id;
+          info.frame_id_ = frame_id;
+          info.parent_ = parent_id;
+          frames_.push_back(info);
+          s1_pos = s2_pos + 1;
+        }
+      }
+    }
+  }
+
+  std::vector<Chunk> parseChunk(const std::string& chunk_std) {
+    std::vector<Chunk> chunks;
+    {
+      // parse chunks
+      size_t s1_pos = 0, s2_pos = 0;
+      unsigned time_begin, time_end, frame_id, type_id, size, number_of_objects;
+
+      while (s2_pos != chunk_std.npos) {
+        // look for the \n symbol
+        // format: frameId, symbolId, parentId
+        s2_pos = chunk_std.find("\n", s1_pos);
+        if (s2_pos != chunk_std.npos) {
+          int c1_e = chunk_std.find(",", s1_pos);
+          std::string c1_s = chunk_std.substr(s1_pos, c1_e - s1_pos);
+          time_begin = atoi(c1_s.c_str());
+
+          int c2_e = chunk_std.find(",", c1_e + 1);
+          std::string c2_s = chunk_std.substr(c1_e + 1, c2_e - c1_e - 1);
+          time_end = atoi(c2_s.c_str());
+
+          int c3_e = chunk_std.find(",", c2_e + 1);
+          std::string c3_s = chunk_std.substr(c2_e + 1, c3_e - c2_e - 1);
+          frame_id = atoi(c3_s.c_str());
+
+          int c4_e = chunk_std.find(",", c3_e + 1);
+          std::string c4_s = chunk_std.substr(c3_e + 1, c4_e - c3_e - 1);
+          type_id = atoi(c4_s.c_str());
+
+          int c5_e = chunk_std.find(",", c4_e + 1);
+          std::string c5_s = chunk_std.substr(c4_e + 1, c5_e - c4_e - 1);
+          size = atoi(c5_s.c_str());
+
+          int c6_e = chunk_std.find(",", c5_e + 1);
+          std::string c6_s = chunk_std.substr(c5_e + 1, c6_e - c5_e - 1);
+          number_of_objects = atoi(c6_s.c_str());
+
+          Chunk chunk;
+          chunk.frame_id_ = frame_id;
+          chunk.number_of_objects_ = number_of_objects;
+          chunk.size_ = size;
+          chunk.time_begin_ = time_begin;
+          chunk.time_end_ = time_end;
+          chunk.type_id_ = type_id;
+          chunks.push_back(chunk);
+          s1_pos = s2_pos + 1;
+        }
+      }
+    }
+    return chunks;
+  }
+
+ private:
+  size_t getFrameIdx(unsigned frame_id) {
+    for (size_t i = 0; i < frames_.size(); i++) {
+      if (frames_[i].frame_id_ == frame_id) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  std::vector<unsigned> findFrame(std::vector<std::string> bu_call_stack) {
+    std::vector<unsigned> frames;
+
+    std::map<std::string, unsigned>::const_iterator cit =
+        symbols_.find(bu_call_stack[0]);
+    if (cit != symbols_.end()) {
+        // take the cit->second and look for it in the frames
+      for (size_t j = 0; j < frames_.size(); j++) {
+        if (frames_[j].callsite_ == cit->second) {
+          bool good_frame = true;
+          // check all other frames iterating by parents
+          unsigned parent_frame = frames_[j].parent_;
+          for (size_t i = 1; i < bu_call_stack.size() && good_frame; i++) {
+            size_t idx = getFrameIdx(parent_frame);
+            if (idx != (size_t)-1) {
+              TestFrameInfo& parent = frames_[idx];
+              std::map<std::string, unsigned>::const_iterator cit2 =
+                  symbols_.find(bu_call_stack[i]);
+              if (cit2 != symbols_.end()) {
+                if (cit2->second == parent.callsite_) {
+                  parent_frame = parent.parent_;
+                } else {
+                  good_frame = false;
+                }
+              } else {
+                good_frame = false;
+              }
+            } else {
+              good_frame = false;
+            }
+          }
+          if (good_frame) {
+            frames.push_back(frames_[j].frame_id_);
+          }
+        }
+      }
+    }
+    return frames;
+  }
+  std::map<std::string, unsigned> symbols_;
+  std::map<std::string, unsigned> types_;
+  // no need to have fast version, it will not be many frames
+  std::vector<TestFrameInfo> frames_;
+};
+
+class TestStatsStreamXDK : public v8::OutputStream {
+ public:
+  explicit TestStatsStreamXDK(XDKHPOutputChecker* checker) :
+    checker_(checker) {}
+  virtual ~TestStatsStreamXDK() {}
+  virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) {
+    DCHECK(false);
+    return kAbort;
+  }
+  virtual WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* data,
+                                          int count) {
+    DCHECK(false);
+    return kAbort;
+  }
+  virtual WriteResult WriteHeapXDKChunk(const char* symbols, int symbolsSize,
+    const char* frames, int framesSize,
+    const char* types, int typesSize,
+    const char* chunks, int chunksSize,
+    const char* retentions, int retentionSize) {
+    checker_->parse(symbols, frames, types);
+    chunk_ = chunks;
+    return kContinue;
+  }
+  void EndOfStream() {}
+
+  std::string GetChunk() {
+    return chunk_;
+  }
+
+ private:
+  XDKHPOutputChecker* checker_;
+  std::string chunk_;
+};
+
+
+TEST(HeapProfilerXDK) {
+  XDKHPOutputChecker checker;
+  LocalContext env2;
+  v8::HandleScope scope(env2->GetIsolate());
+  v8::HeapProfiler* heap_profiler = env2->GetIsolate()->GetHeapProfiler();
+  TestStatsStreamXDK stream(&checker);
+  heap_profiler->StartTrackingHeapObjectsXDK(8, false, true);
+
+  // To have repeatable test we need to warm-up the heap and optimization v8
+  // techniques (like inlining). So, we create 100 objects, not the only one
+  CompileRun(
+    "function A1() { this.string = 'This is a string';}\n"
+    "function object2() {\n"
+    "  this.elem = [];\n"
+    "  this.third = [];\n"
+    "}"
+    "var globalA2 = [];\n"
+    "function allocFunction2() {\n"
+    "  globalA2.push(new object2());\n"
+    "}\n"
+    "for (var i=0; i<100; i++) allocFunction2();\n");
+
+  heap_profiler->GetHeapXDKStats(&stream);
+  CompileRun("allocFunction2();\n");
+  heap_profiler->GetHeapXDKStats(&stream);
+  CompileRun("delete globalA2[99];\n");
+  heap_profiler->GetHeapXDKStats(&stream);
+  std::string chunk_deleted_globalA2_0_array = stream.GetChunk();
+  v8::HeapEventXDK* event = heap_profiler->StopTrackingHeapObjectsXDK();
+
+  // adding the latest info:
+  checker.parse(event->getSymbols(), event->getFrames(), event->getTypes());
+
+  // here should be 2 arrays and 1 object2
+  TestObjectInfo info_deleted_globalA2_0_array;
+  info_deleted_globalA2_0_array.bu_call_stack_.push_back("object2");
+  info_deleted_globalA2_0_array.bu_call_stack_.push_back("allocFunction2");
+  info_deleted_globalA2_0_array.type_ = "Array";
+  info_deleted_globalA2_0_array.number_of_objects_ = 0;
+  bool idg_arr_jad = checker.checkObjectsExists(
+      info_deleted_globalA2_0_array, chunk_deleted_globalA2_0_array);
+
+  TestObjectInfo info_deleted_globalA2_0;
+  info_deleted_globalA2_0.bu_call_stack_.push_back("allocFunction2");
+  info_deleted_globalA2_0.type_ = "object2";
+  info_deleted_globalA2_0.number_of_objects_ = 1;
+  bool idg_obj_jad = checker.checkObjectsExists(
+      info_deleted_globalA2_0, chunk_deleted_globalA2_0_array);
+
+  // here should be 2 arrays and 1 object2
+  TestObjectInfo info_deleted_globalA2_1_array;
+  info_deleted_globalA2_1_array.bu_call_stack_.push_back("object2");
+  info_deleted_globalA2_1_array.bu_call_stack_.push_back("allocFunction2");
+  info_deleted_globalA2_1_array.type_ = "Array";
+  info_deleted_globalA2_1_array.number_of_objects_ = 2;
+  bool idg_arr_end = checker.checkObjectsExists(
+      info_deleted_globalA2_1_array, event->getChunks());
+
+  TestObjectInfo info_deleted_globalA2_1;
+  info_deleted_globalA2_1.bu_call_stack_.push_back("allocFunction2");
+  info_deleted_globalA2_1.type_ = "object2";
+  info_deleted_globalA2_1.number_of_objects_ = 1;
+  bool idg_obj_end = checker.checkObjectsExists(
+      info_deleted_globalA2_1, event->getChunks());
+  // find objects anywhere
+  CHECK_EQ(true, idg_obj_end || idg_obj_jad);
+  CHECK_EQ(true, idg_arr_end || idg_arr_jad);
+}
+
+
+TEST(HeapProfilerXDKRetentionStorage) {
+  v8::internal::RefId parent;
+  v8::internal::RefId rf11, rf12, rf13, rf21, rf22, rf23;
+  v8::internal::RefSet set1, set2, set3;
+  v8::internal::References refs;
+
+  parent.stackId_ = 99;
+  parent.classId_ = 99;
+
+  rf11.stackId_ = 10; rf11.classId_ = 1; rf11.field_ = "one_";
+  set1.references_.insert(rf11);
+  rf12.stackId_ = 20; rf12.classId_ = 1; rf12.field_ = "two_";
+  set1.references_.insert(rf12);
+  rf13.stackId_ = 30; rf13.classId_ = 2; rf13.field_ = "three_";
+  set1.references_.insert(rf13);
+  refs.addReference(parent, set1, 0);
+
+  rf21.stackId_ = 10; rf21.classId_ = 1; rf21.field_ = "eno_";
+  set2.references_.insert(rf21);
+  rf22.stackId_ = 15; rf22.classId_ = 1; rf22.field_ = "owt_";
+  set2.references_.insert(rf22);
+  rf23.stackId_ = 30; rf23.classId_ = 2; rf23.field_ = "eerht_";
+  set2.references_.insert(rf23);
+  refs.addReference(parent, set2, 0);
+
+  set3.references_.insert(rf11);
+  set3.references_.insert(rf12);
+  set3.references_.insert(rf13);
+  refs.addReference(parent, set3, 0);
+
+  // there should be two records by set1 and one by set2
+  std::string str = refs.serialize();
+
+  CHECK_EQ(true,
+       str.find("99,99,1,0,2,10,1,one_,20,1,two_,30,2,three_") != str.npos &&
+       str.find("99,99,1,0,1,10,1,eno_,15,1,owt_,30,2,eerht_") != str.npos);
+}
index a29a91b..ec4f113 100644 (file)
         '../../src/zone.h',
         '../../third_party/fdlibm/fdlibm.cc',
         '../../third_party/fdlibm/fdlibm.h',
+        '../../src/xdk-allocation.cc',
+        '../../src/xdk-allocation.h',
+        '../../src/xdk-utils.h',
+        '../../src/xdk-utils.cc',
       ],
       'conditions': [
         ['want_separate_host_toolset==1', {
index 3cf6979..0e17340 100644 (file)
 # Edit these when rolling DEPS.xwalk.
 # -----------------------------------
 
-chromium_crosswalk_rev = '88fc58a654d73e2df3dffc946077486c450f3bdb'
-blink_crosswalk_rev = 'ed2bae8ced284782cbd55f1597e02d6ee621621b'
-v8_crosswalk_rev = '390bd33f39ea5a12e403ebb52f8b553b0772aa2c'
-ozone_wayland_rev = '9a04e61a2c373bc02dce2b6dfac6f56d99981598'
+chromium_crosswalk_rev = '52d4347d95a66afe54be98677b077fce0b7fd846'
+v8_crosswalk_rev = '35e0d97482e74df63e75088eec0378f19bad24dd'
+ozone_wayland_rev = '8f3a1b59dd183087269400208947031cac5fcfcd'
+
+# |blink_crosswalk_rev| specifies the SHA1 hash of the blink-crosswalk commit
+# we want to point to, very much like the variables above.
+# |blink_upstream_rev| indicates the revision of the latest upstream commit in
+# the blink-crosswalk repository, so that the devtools code can use it to fetch
+# assets from Chromium's servers with a revision that exists there. We need an
+# SVN revision while Blink is still in SVN.
+blink_crosswalk_rev = 'a6caf4f53deee46eb41c31d38dc990964615b8e5'
+blink_upstream_rev = '184144'  # FIXME(wang16): Specify a later revision than
+                               # the one we actually have in blink-crosswalk
+                               # because of crbug.com/425155.
+                               # This will not be needed in M40 or M39 past
+                               # Blink r184144.
 
 crosswalk_git = 'https://github.com/crosswalk-project'
 ozone_wayland_git = 'https://github.com/01org'
@@ -64,6 +76,15 @@ solutions = [
       'commit-queue': None,
       'depot_tools': None,
     },
+
+    'custom_hooks': [
+      # Disable Chromium's "gyp" hooks, which runs the gyp_chromium script. We
+      # are not interested in running it as we use gyp_xwalk instead (and it is
+      # run at a later stage as a hook in Crosswalk's own DEPS).
+      {
+        'name': 'gyp',
+      },
+    ],
   },
 
   # ozone-wayland is set as a separate solution because we gclient _not_ to read
@@ -76,6 +97,21 @@ solutions = [
   }
 ]
 
+hooks = [
+  {
+    'action': [
+      'python',
+      'src/xwalk/tools/upstream_revision.py',
+      '-r',
+      blink_upstream_rev,
+      '-o',
+      'src/xwalk/build/UPSTREAM.blink'
+    ],
+    'pattern': '.',
+    'name': 'upstream_revision'
+  }
+]
+
 # -------------------------------------------------
 # This area is edited by generate_gclient-xwalk.py.
 # -------------------------------------------------
index 4efecb8..15185d3 100644 (file)
@@ -1,4 +1,4 @@
-MAJOR=10
+MAJOR=11
 MINOR=39
-BUILD=234
+BUILD=244
 PATCH=0
index 92c2a38..ad3e383 100644 (file)
@@ -6,11 +6,9 @@ package org.xwalk.app;
 
 import android.app.Activity;
 import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
@@ -33,8 +31,6 @@ public abstract class XWalkRuntimeActivityBase extends XWalkActivity {
 
     private boolean mShownNotFoundDialog = false;
 
-    private BroadcastReceiver mReceiver;
-
     private boolean mRemoteDebugging = false;
 
     private boolean mUseAnimatableView = false;
@@ -45,27 +41,6 @@ public abstract class XWalkRuntimeActivityBase extends XWalkActivity {
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        IntentFilter intentFilter = new IntentFilter("org.xwalk.intent");
-        intentFilter.addAction("android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE");
-        intentFilter.addAction("android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE");
-        mReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                Bundle bundle = intent.getExtras();
-                if (bundle == null)
-                    return;
-
-                if (bundle.containsKey("remotedebugging")) {
-                    String extra = bundle.getString("remotedebugging");
-                    if (extra.equals("true")) {
-                        XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);
-                    } else if (extra.equals("false")) {
-                        XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, false);
-                    }
-                }
-            }
-        };
-        registerReceiver(mReceiver, intentFilter);
         super.onCreate(savedInstanceState);
         tryLoadRuntimeView();
         if (mRuntimeView != null) mRuntimeView.onCreate();
@@ -99,7 +74,6 @@ public abstract class XWalkRuntimeActivityBase extends XWalkActivity {
 
     @Override
     public void onDestroy() {
-        unregisterReceiver(mReceiver);
         if (mExtensionManager != null) mExtensionManager.onDestroy();
         super.onDestroy();
     }
index c0a7c03..7f59f49 100644 (file)
@@ -4,7 +4,10 @@
 
 package org.xwalk.runtime.client.embedded.shell;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Bundle;
 import android.os.Looper;
 import android.os.MessageQueue;
@@ -23,12 +26,14 @@ import android.widget.TextView.OnEditorActionListener;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.content.browser.TracingControllerAndroid;
 import org.xwalk.app.XWalkRuntimeActivityBase;
+import org.xwalk.core.XWalkPreferences;
 
 public class XWalkRuntimeClientEmbeddedShellActivity extends XWalkRuntimeActivityBase {
     // TODO(yongsheng): Add one flag to hide the url bar.
     private static final String TAG = XWalkRuntimeClientEmbeddedShellActivity.class.getName();
 
     private EditText mUrlTextView;
+    private BroadcastReceiver mReceiver;
     private TracingControllerAndroid mTracingController;
 
     TracingControllerAndroid getTracingController() {
@@ -40,12 +45,27 @@ public class XWalkRuntimeClientEmbeddedShellActivity extends XWalkRuntimeActivit
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        IntentFilter intentFilter = new IntentFilter("org.xwalk.intent");
+        intentFilter.addAction("android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE");
+        intentFilter.addAction("android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE");
+        mReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Bundle bundle = intent.getExtras();
+                if (bundle == null) return;
+
+                XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING,
+                        Boolean.parseBoolean(bundle.getString("remotedebugging", "false")));
+            }
+        };
+        registerReceiver(mReceiver, intentFilter);
         super.onCreate(savedInstanceState);
         registerTracingReceiverWhenIdle();
     }
 
     @Override
     public void onDestroy() {
+        unregisterReceiver(mReceiver);
         super.onDestroy();
         unregisterTracingReceiver();
     }
index 6e33e54..789ea40 100644 (file)
@@ -4,7 +4,10 @@
 
 package org.xwalk.runtime.client.shell;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Bundle;
 import android.view.KeyEvent;
 import android.view.View;
@@ -18,18 +21,40 @@ import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
 import org.xwalk.app.XWalkRuntimeActivityBase;
+import org.xwalk.core.XWalkPreferences;
 
 public class XWalkRuntimeClientShellActivity extends XWalkRuntimeActivityBase {
     // TODO(yongsheng): Add one flag to hide the url bar.
     private static final String TAG = XWalkRuntimeClientShellActivity.class.getName();
 
     private EditText mUrlTextView;
+    private BroadcastReceiver mReceiver;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        IntentFilter intentFilter = new IntentFilter("org.xwalk.intent");
+        intentFilter.addAction("android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE");
+        intentFilter.addAction("android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE");
+        mReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Bundle bundle = intent.getExtras();
+                if (bundle == null) return;
+
+                XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING,
+                        Boolean.parseBoolean(bundle.getString("remotedebugging", "false")));
+            }
+        };
+        registerReceiver(mReceiver, intentFilter);
         super.onCreate(savedInstanceState);
     }
 
+    @Override
+    public void onDestroy() {
+        unregisterReceiver(mReceiver);
+        super.onDestroy();
+    }
+
     private static String sanitizeUrl(String url) {
         if (url == null) return url;
         if (url.startsWith("www.") || url.indexOf(":") == -1) url = "http://" + url;
index eb2d7b6..bcb9e0f 100755 (executable)
@@ -24,6 +24,7 @@ from handle_xml import AddElementAttribute
 from handle_xml import AddElementAttributeAndText
 from handle_xml import EditElementAttribute
 from handle_xml import EditElementValueByNodeName
+from handle_xml import MergeNodes
 from handle_permissions import HandlePermissions
 from util import CleanDir, CreateAndCopyDir, GetBuildDir
 from xml.dom import minidom
@@ -447,6 +448,25 @@ def CustomizeExtensions(app_info, extensions):
         file_handle = open(manifest_path, 'w')
         xmldoc.writexml(file_handle, encoding='utf-8')
         file_handle.close()
+      if 'manifest' in json_output:
+        manifest_merge_path = os.path.join(source_path, json_output['manifest'])
+        if not os.path.isfile(manifest_merge_path):
+          print('Error: %s specified in the extension\'s JSON '
+                'could not be found.' % manifest_merge_path)
+          sys.exit(9)
+        xmldoc_merge = minidom.parse(manifest_merge_path)
+        manifest_nodes = xmldoc.getElementsByTagName('manifest')
+        manifest_nodes_merge = xmldoc_merge.getElementsByTagName('manifest')
+        if not manifest_nodes:
+          print('Error: %s does not have a <manifest> node.' % manifest_path)
+          sys.exit(9)
+        if not manifest_nodes_merge:
+          print('Error: %s does not have a <manifest> node.'
+                % manifest_merge_path)
+          sys.exit(9)
+        MergeNodes(manifest_nodes[0], manifest_nodes_merge[0])
+        with open(manifest_path, 'w') as file_handle:
+          xmldoc.writexml(file_handle, encoding='utf-8')
 
   # Write configuration of extensions into the target extensions-config.json.
   if extension_json_list:
index e9898b5..b9fe761 100755 (executable)
@@ -39,3 +39,36 @@ def AddElementAttributeAndText(doc, node, name, value, data):
   text = doc.createTextNode(data)
   item.appendChild(text)
   root.appendChild(item)
+
+
+def CompareNodes(node1, node2):
+  if node1.tagName != node2.tagName or node1.attributes is None:
+    return False
+  if node2.attributes is None:
+    return True
+
+  for item in node2.attributes.items():
+    if not item in node1.attributes.items():
+      return False
+  return True
+
+
+def MergeNodes(node1, node2):
+  tmp_node_list = []
+  for item2 in node2.childNodes:
+    if item2.nodeType != item2.ELEMENT_NODE:
+      continue
+    item1 = None
+    for tmp_item in node1.childNodes:
+      if tmp_item.nodeType != tmp_item.ELEMENT_NODE:
+        continue
+      if CompareNodes(tmp_item, item2):
+        item1 = tmp_item
+        break
+    if item1 is not None:
+      MergeNodes(item1, item2)
+    else:
+      tmp_node_list.append(item2)
+
+  for item in tmp_node_list:
+    node1.appendChild(item)
index 224967d..fd04ff2 100755 (executable)
@@ -764,6 +764,26 @@ class TestMakeApk(unittest.TestCase):
     self.assertTrue(content.find('android.permission.READ_CONTACTS') != -1)
     self.checkApks('Example', '1.0.0')
 
+  def testExtensionWithAndroidManifest(self):
+    test_entry_root = 'test_data/entry'
+    # Add redundant separators for test.
+    extension_path = 'test_data//extensions/adextension/'
+    cmd = ['python', 'make_apk.py', '--name=Example', '--app-version=1.0.0',
+           '--package=org.xwalk.example', '--app-root=%s' % test_entry_root,
+           '--app-local-path=contactextension.html',
+           '--extensions=%s' % extension_path,
+           '--project-dir=.', self._mode]
+    RunCommand(cmd)
+    self.addCleanup(Clean, 'Example', '1.0.0')
+    self.assertTrue(os.path.exists('Example'))
+    manifest = 'Example/AndroidManifest.xml'
+    with open(manifest, 'r') as content_file:
+      content = content_file.read()
+    self.assertTrue(os.path.exists(manifest))
+    self.assertTrue(content.find('_GOOGLE_PLAY_SERVICES_LIB_VERSION_') != -1)
+    self.checkApks('Example', '1.0.0')
+
+
   def testXPK(self):
     xpk_file = os.path.join('test_data', 'xpk', 'example.xpk')
     cmd = ['python', 'make_apk.py', '--package=org.xwalk.example',
@@ -1164,6 +1184,7 @@ def SuiteWithModeOption():
   test_suite.addTest(TestMakeApk('testEntryWithErrors'))
   test_suite.addTest(TestMakeApk('testExtensionsWithOneExtension'))
   test_suite.addTest(TestMakeApk('testExtensionsWithNonExtension'))
+  test_suite.addTest(TestMakeApk('testExtensionWithAndroidManifest'))
   test_suite.addTest(TestMakeApk('testExtensionWithPermissions'))
   test_suite.addTest(TestMakeApk('testFullscreen'))
   test_suite.addTest(TestMakeApk('testIconByOption'))
diff --git a/src/xwalk/app/tools/android/test_data/extensions/adextension/AndroidManifest.xml b/src/xwalk/app/tools/android/test_data/extensions/adextension/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..39eea77
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+    <application android:name="org.xwalk.core.XWalkApplication">
+        <meta-data android:name="com.google.android.gms.version" android:value="_GOOGLE_PLAY_SERVICES_LIB_VERSION_"/>
+    </application>
+</manifest>
diff --git a/src/xwalk/app/tools/android/test_data/extensions/adextension/adextension.js b/src/xwalk/app/tools/android/test_data/extensions/adextension/adextension.js
new file mode 100644 (file)
index 0000000..cddba60
--- /dev/null
@@ -0,0 +1,5 @@
+// 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.
+
+//This is a dummy file
diff --git a/src/xwalk/app/tools/android/test_data/extensions/adextension/adextension.json b/src/xwalk/app/tools/android/test_data/extensions/adextension/adextension.json
new file mode 100644 (file)
index 0000000..3e6f779
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "name":  "Ad",
+  "class": "com.example.extension.AdExtension",
+  "jsapi": "adextension.js",
+  "manifest": "AndroidManifest.xml"
+}
diff --git a/src/xwalk/app/tools/android/test_data/extensions/adextension/src/com/example/extension/AdExtension.java b/src/xwalk/app/tools/android/test_data/extensions/adextension/src/com/example/extension/AdExtension.java
new file mode 100644 (file)
index 0000000..f6317c2
--- /dev/null
@@ -0,0 +1,11 @@
+package com.example.extension;
+
+import org.xwalk.app.runtime.extension.XWalkExtensionClient;
+import org.xwalk.app.runtime.extension.XWalkExtensionContextClient;
+
+public class AdExtension extends XWalkExtensionClient {
+    // Don't change the parameters in Constructor because XWalk needs to call this constructor.
+    public AdExtension(String name, String JsApi, XWalkExtensionContextClient context) {
+        super(name, JsApi, context);
+    }
+}
index e0b526f..8b7acc4 100644 (file)
@@ -23,6 +23,7 @@
 #include "xwalk/application/common/manifest_handlers/warp_handler.h"
 #include "xwalk/runtime/browser/runtime.h"
 #include "xwalk/runtime/browser/runtime_context.h"
+#include "xwalk/runtime/browser/runtime_defered_ui_strategy.h"
 #include "xwalk/runtime/browser/xwalk_runner.h"
 
 #if defined(OS_TIZEN)
@@ -90,6 +91,7 @@ Application::Application(
       security_mode_enabled_(false),
       runtime_context_(runtime_context),
       observer_(NULL),
+      ui_strategy_(new RuntimeDeferedUIStrategy),
       remote_debugging_enabled_(false),
       weak_factory_(this) {
   DCHECK(runtime_context_);
@@ -229,10 +231,11 @@ bool Application::Launch(const LaunchParams& launch_params) {
   params.state = is_wgt ?
       GetWindowShowState<Manifest::TYPE_WIDGET>(launch_params):
       GetWindowShowState<Manifest::TYPE_MANIFEST>(launch_params);
+  window_show_params_.state = params.state;
 
   params.splash_screen_path = GetSplashScreenPath();
 
-  runtime->AttachWindow(params);
+  ui_strategy_->Show(runtime, params);
 
   return true;
 }
@@ -261,6 +264,8 @@ int Application::GetRenderProcessHostID() const {
 void Application::OnRuntimeAdded(Runtime* runtime) {
   DCHECK(runtime);
   runtime->set_remote_debugging_enabled(remote_debugging_enabled_);
+  if (!runtimes_.empty())
+    ui_strategy_->Show(runtime, window_show_params_);
   runtimes_.insert(runtime);
 }
 
@@ -268,14 +273,10 @@ void Application::OnRuntimeRemoved(Runtime* runtime) {
   DCHECK(runtime);
   runtimes_.erase(runtime);
 
-  if (runtimes_.empty()) {
-#if defined(OS_TIZEN_MOBILE)
-    runtime->CloseRootWindow();
-#endif
+  if (runtimes_.empty())
     base::MessageLoop::current()->PostTask(FROM_HERE,
         base::Bind(&Application::NotifyTermination,
                    weak_factory_.GetWeakPtr()));
-  }
 }
 
 void Application::RenderProcessExited(RenderProcessHost* host,
index 365b63e..24522e2 100644 (file)
@@ -22,6 +22,7 @@
 #include "xwalk/application/common/application_data.h"
 #include "xwalk/application/common/security_policy.h"
 #include "xwalk/runtime/browser/runtime.h"
+#include "xwalk/runtime/browser/runtime_ui_strategy.h"
 
 
 namespace content {
@@ -112,11 +113,17 @@ class Application : public Runtime::Observer,
 
   void set_observer(Observer* observer) { observer_ = observer; }
 
+  RuntimeUIStrategy* ui_strategy() { return ui_strategy_.get(); }
+
  protected:
   Application(scoped_refptr<ApplicationData> data, RuntimeContext* context);
   virtual bool Launch(const LaunchParams& launch_params);
   virtual void InitSecurityPolicy();
 
+  // Runtime::Observer implementation.
+  virtual void OnRuntimeAdded(Runtime* runtime) OVERRIDE;
+  virtual void OnRuntimeRemoved(Runtime* runtime) OVERRIDE;
+
   // Get the path of splash screen image. Return empty path by default.
   // Sub class can override it to return a specific path.
   virtual base::FilePath GetSplashScreenPath();
@@ -129,6 +136,9 @@ class Application : public Runtime::Observer,
   content::WebContents* web_contents_;
   bool security_mode_enabled_;
 
+  scoped_ptr<RuntimeUIStrategy> ui_strategy_;
+  xwalk::NativeAppWindow::CreateParams window_show_params_;
+
   base::WeakPtr<Application> GetWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
@@ -138,9 +148,6 @@ class Application : public Runtime::Observer,
   friend class ApplicationService;
   static scoped_ptr<Application> Create(scoped_refptr<ApplicationData> data,
       RuntimeContext* context);
-  // Runtime::Observer implementation.
-  virtual void OnRuntimeAdded(Runtime* runtime) OVERRIDE;
-  virtual void OnRuntimeRemoved(Runtime* runtime) OVERRIDE;
 
   // content::RenderProcessHostObserver implementation.
   virtual void RenderProcessExited(content::RenderProcessHost* host,
index 5c355f3..1b59dbe 100644 (file)
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "content/browser/renderer_host/media/audio_renderer_host.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/screen_orientation_dispatcher_host.h"
 
 namespace xwalk {
 
+namespace keys = application_manifest_keys;
 namespace widget_keys = application_widget_keys;
 
 namespace application {
 
+const char kDefaultMediaAppClass[] = "player";
+namespace {
+#if defined(OS_TIZEN_MOBILE)
+void ApplyRootWindowParams(Runtime* runtime,
+                           NativeAppWindow::CreateParams* params) {
+  if (!params->delegate)
+    params->delegate = runtime;
+  if (params->bounds.IsEmpty())
+    params->bounds = gfx::Rect(0, 0, 840, 600);
+
+  unsigned int fullscreen_options = runtime->fullscreen_options();
+  if (params->state == ui::SHOW_STATE_FULLSCREEN)
+    fullscreen_options |= Runtime::FULLSCREEN_FOR_LAUNCH;
+  else
+    fullscreen_options &= ~Runtime::FULLSCREEN_FOR_LAUNCH;
+  runtime->set_fullscreen_options(fullscreen_options);
+}
+
+NativeAppWindow* CreateRootWindow(Runtime* runtime,
+                                  const NativeAppWindow::CreateParams& params) {
+  NativeAppWindow::CreateParams effective_params(params);
+  ApplyRootWindowParams(runtime, &effective_params);
+  return NativeAppWindow::Create(effective_params);
+}
+#endif
+}  // namespace
+
 blink::WebScreenOrientationLockType GetDefaultOrientation(
     const base::WeakPtr<Application>& app) {
   TizenSettingInfo* info = static_cast<TizenSettingInfo*>(
@@ -100,6 +130,9 @@ ApplicationTizen::ApplicationTizen(
     scoped_refptr<ApplicationData> data,
     RuntimeContext* runtime_context)
     : Application(data, runtime_context),
+#if defined(OS_TIZEN_MOBILE)
+      root_window_(NULL),
+#endif
       is_suspended_(false) {
 #if defined(USE_OZONE)
   ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
@@ -133,7 +166,31 @@ void ApplicationTizen::Show() {
 
 bool ApplicationTizen::Launch(const LaunchParams& launch_params) {
   if (Application::Launch(launch_params)) {
+#if defined(OS_TIZEN_MOBILE)
+    if (!runtimes_.empty()) {
+      root_window_ = CreateRootWindow(*(runtimes_.begin()),
+                                      window_show_params_);
+      window_show_params_.parent = root_window_->GetNativeWindow();
+      root_window_->Show();
+    }
+#endif
     DCHECK(web_contents_);
+
+    // Get media class of application.
+    const Manifest* manifest = data_->GetManifest();
+    std::string app_class;
+    manifest->GetString(keys::kXWalkMediaAppClass, &app_class);
+    if (app_class.empty())
+      app_class = kDefaultMediaAppClass;
+
+    // Set an application ID and class, which are needed to tag audio
+    // streams in pulseaudio/Murphy.
+    scoped_refptr<content::AudioRendererHost> audio_host =
+        static_cast<content::RenderProcessHostImpl*>(render_process_host_)
+            ->audio_renderer_host();
+    if (audio_host.get())
+      audio_host->SetMediaStreamProperties(id(), app_class);
+
     content::ScreenOrientationProvider *provider =
         new ScreenOrientationProviderTizen(GetWeakPtr());
     web_contents_->GetScreenOrientationDispatcherHost()->SetProvider(provider);
@@ -226,5 +283,25 @@ void ApplicationTizen::SetUserAgentString(
   cookie_manager_->SetUserAgentString(render_process_host_, user_agent_string);
 }
 
+void ApplicationTizen::OnRuntimeAdded(Runtime* runtime) {
+  DCHECK(runtime);
+  Application::OnRuntimeAdded(runtime);
+#if defined(OS_TIZEN_MOBILE)
+  if (root_window_ && runtimes_.size() > 1)
+      root_window_->Show();
+#endif
+}
+
+void ApplicationTizen::OnRuntimeRemoved(Runtime* runtime) {
+  DCHECK(runtime);
+  Application::OnRuntimeRemoved(runtime);
+#if defined(OS_TIZEN_MOBILE)
+  if (runtimes_.empty() && root_window_) {
+    root_window_->Close();
+    root_window_ = NULL;
+  }
+#endif
+}
+
 }  // namespace application
 }  // namespace xwalk
index 6302ad8..ef3d741 100644 (file)
@@ -42,11 +42,18 @@ class ApplicationTizen :  // NOLINT
 
   virtual base::FilePath GetSplashScreenPath() OVERRIDE;
 
+  // Runtime::Observer implementation.
+  virtual void OnRuntimeAdded(Runtime* runtime) OVERRIDE;
+  virtual void OnRuntimeRemoved(Runtime* runtime) OVERRIDE;
+
 #if defined(USE_OZONE)
   virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
   virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE;
 #endif
 
+#if defined(OS_TIZEN_MOBILE)
+  NativeAppWindow* root_window_;
+#endif
   scoped_ptr<CookieManager> cookie_manager_;
   bool is_suspended_;
 };
index 419975a..19b7aca 100644 (file)
@@ -293,8 +293,7 @@ base::DictionaryValue* LoadXMLNode(
       DCHECK(temp->IsType(base::Value::TYPE_DICTIONARY));
       base::DictionaryValue* dict;
       temp->GetAsDictionary(&dict);
-      base::DictionaryValue* prev_value(new base::DictionaryValue());
-      prev_value = dict->DeepCopy();
+      base::DictionaryValue* prev_value = dict->DeepCopy();
 
       base::ListValue* list = new base::ListValue();
       list->Append(prev_value);
index 5decf4c..8a960cc 100644 (file)
@@ -63,6 +63,7 @@ const char kXWalkLaunchScreenReadyWhen[] =
 #if defined(OS_TIZEN)
 const char kTizenAppIdKey[] = "tizen_app_id";
 const char kIcon128Key[] = "icons.128";
+const char kXWalkMediaAppClass[] = "xwalk_media_app_class";
 #endif
 
 }  // namespace application_manifest_keys
@@ -114,6 +115,7 @@ const char kAllowNavigationKey[] = "widget.allow-navigation.#text";
 const char kCSPReportOnlyKey[] =
     "widget.content-security-policy-report-only.#text";
 const char kTizenSettingKey[] = "widget.setting";
+const char kTizenContextMenuKey[] = "widget.setting.@context-menu";
 const char kTizenHardwareKey[] = "widget.setting.@hwkey-event";
 const char kTizenEncryptionKey[] = "widget.setting.@encryption";
 const char kTizenMetaDataKey[] = "widget.metadata";
index ba74e95..a67dcc3 100644 (file)
@@ -56,6 +56,7 @@ namespace application_manifest_keys {
 #if defined(OS_TIZEN)
   extern const char kTizenAppIdKey[];
   extern const char kIcon128Key[];
+  extern const char kXWalkMediaAppClass[];
 #endif
 }  // namespace application_manifest_keys
 
@@ -96,6 +97,7 @@ namespace application_widget_keys {
   extern const char kAllowNavigationKey[];
   extern const char kCSPReportOnlyKey[];
   extern const char kTizenSettingKey[];
+  extern const char kTizenContextMenuKey[];
   extern const char kTizenHardwareKey[];
   extern const char kTizenEncryptionKey[];
   extern const char kTizenMetaDataKey[];
index 8a84774..8427a29 100644 (file)
@@ -1,4 +1,5 @@
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,6 +20,7 @@ const char kGeneratedMainDocumentFilename[] =
     "_generated_main_document.html";
 const base::FilePath::CharType kCookieDatabaseFilename[] =
     FILE_PATH_LITERAL("ApplicationCookies");
+const char kTizenWebAPIVersion[] = "2.2";
 
 }  // namespace application
 }  // namespace xwalk
index 3878fe0..373739c 100644 (file)
@@ -1,4 +1,5 @@
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,6 +29,9 @@ extern const char kGeneratedMainDocumentFilename[];
 // The name of cookies database file.
 extern const base::FilePath::CharType kCookieDatabaseFilename[];
 
+// The Tizen Web API version is supported
+extern const char kTizenWebAPIVersion[];
+
 }  // namespace application
 }  // namespace xwalk
 
index 05ff054..46d92eb 100644 (file)
@@ -1,4 +1,5 @@
 // Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,8 +10,10 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "base/strings/string_split.h"
+#include "base/version.h"
 #include "third_party/re2/re2/re2.h"
 #include "xwalk/application/common/application_manifest_constants.h"
+#include "xwalk/application/common/constants.h"
 
 namespace xwalk {
 
@@ -99,14 +102,19 @@ bool TizenApplicationHandler::Validate(
                          " 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;
   }
 
+  const base::Version supported_version = Version(kTizenWebAPIVersion);
+  if (supported_version.IsOlderThan(app_info->required_version())) {
+    *error = std::string("The required_version of Tizen Web API"
+                         " is not supported.\n");
+    return false;
+  }
+
   return true;
 }
 
index b5f4c36..d684591 100644 (file)
@@ -49,6 +49,10 @@ bool TizenSettingHandler::Parse(scoped_refptr<ApplicationData> application,
   manifest->GetString(keys::kTizenEncryptionKey, &encryption);
   app_info->set_encryption_enabled(encryption == "enable");
 
+  std::string context_menu;
+  manifest->GetString(keys::kTizenContextMenuKey, &context_menu);
+  app_info->set_context_menu_enabled(context_menu != "disable");
+
   application->SetManifestData(keys::kTizenSettingKey,
                                app_info.release());
   return true;
@@ -85,6 +89,15 @@ bool TizenSettingHandler::Validate(
                          "or not specified in configuration file.");
     return false;
   }
+  std::string context_menu;
+  manifest->GetString(keys::kTizenContextMenuKey, &context_menu);
+  if (!context_menu.empty() &&
+      context_menu != "enable" &&
+      context_menu != "disable") {
+    *error = std::string("The context-menu value must be 'enable'/'disable', "
+                         "or not specified in configuration file.");
+    return false;
+  }
   return true;
 }
 
index bec58e4..5cc5aef 100644 (file)
@@ -38,10 +38,16 @@ class TizenSettingInfo : public ApplicationData::ManifestData {
   void set_encryption_enabled(bool enabled) { encryption_enabled_ = enabled; }
   bool encryption_enabled() const { return encryption_enabled_; }
 
+  void set_context_menu_enabled(bool enabled) {
+    context_menu_enabled_ = enabled;
+  }
+  bool context_menu_enabled() const { return context_menu_enabled_; }
+
  private:
   bool hwkey_enabled_;
   ScreenOrientation screen_orientation_;
   bool encryption_enabled_;
+  bool context_menu_enabled_;
 };
 
 class TizenSettingHandler : public ManifestHandler {
index 947410e..dfc992e 100644 (file)
@@ -3,24 +3,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <stdlib.h>
 #include <stdbool.h>
 #include <stdio.h>
-#include <glib.h>
+#include <stdlib.h>
+
 #include <gio/gio.h>
+#include <glib.h>
 
 #include "base/at_exit.h"
 #include "base/files/file_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/path_service.h"
-
+#include "xwalk/application/common/id_util.h"
 #include "xwalk/application/common/tizen/application_storage.h"
 #include "xwalk/application/tools/linux/dbus_connection.h"
 #include "xwalk/application/tools/tizen/xwalk_package_installer.h"
-#include "xwalk/runtime/common/xwalk_paths.h"
-
-#include "xwalk/application/common/id_util.h"
 #include "xwalk/application/tools/tizen/xwalk_tizen_user.h"
+#include "xwalk/runtime/common/xwalk_paths.h"
 
 using xwalk::application::ApplicationData;
 using xwalk::application::ApplicationStorage;
@@ -29,7 +28,7 @@ namespace {
 
 char* install_path = NULL;
 char* uninstall_id = NULL;
-char* reinstall_path = NULL;
+char* reinstall_id = NULL;
 char* operation_key = NULL;
 int quiet = 0;
 
@@ -42,8 +41,10 @@ GOptionEntry entries[] = {
     "Uninstall the application with this appid/pkgid", "ID" },
   { "continue", 'c' , 0, G_OPTION_ARG_NONE, &continue_tasks,
     "Continue the previous unfinished tasks.", NULL},
-  { "reinstall", 'r', 0, G_OPTION_ARG_STRING, &reinstall_path,
-    "Reinstall the application with path", "PATH" },
+  { "reinstall", 'r', 0, G_OPTION_ARG_STRING, &reinstall_id,
+    "Reinstall the application with this pkgid "
+    "(This option is ONLY for SDK to support RDS mode"
+    " (Rapid Development Support).", "ID" },
   { "key", 'k', 0, G_OPTION_ARG_STRING, &operation_key,
     "Unique operation key", "KEY" },
   { "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
@@ -110,9 +111,8 @@ int main(int argc, char* argv[]) {
     }
   } else if (uninstall_id) {
     success = installer->Uninstall(uninstall_id);
-  } else if (reinstall_path) {
-    success = installer->Reinstall(
-        base::MakeAbsoluteFilePath(base::FilePath(reinstall_path)));
+  } else if (reinstall_id) {
+    success = installer->Reinstall(reinstall_id);
   }
   return success ? 0 : 1;
 }
index edb59b4..d43c8a3 100644 (file)
@@ -163,16 +163,16 @@ void PkgmgrBackendPlugin::SaveInfo(
   std::string pkg_id = app_data->GetPackageID();
   if (force_type.empty())
     strncpy(pkg_detail_info->pkg_type,
-        xwalk::application::GetPackageType(pkg_id).c_str(),
-        PKG_TYPE_STRING_LEN_MAX - 1);
+            xwalk::application::GetPackageType(pkg_id).c_str(),
+            PKG_TYPE_STRING_LEN_MAX - 1);
   else  // force package type
     strncpy(pkg_detail_info->pkg_type,
-        force_type.c_str(),
-        PKG_TYPE_STRING_LEN_MAX - 1);
+            force_type.c_str(),
+            PKG_TYPE_STRING_LEN_MAX - 1);
   strncpy(pkg_detail_info->pkg_name, pkg_id.c_str(),
-      PKG_NAME_STRING_LEN_MAX - 1);
+          PKG_NAME_STRING_LEN_MAX - 1);
   strncpy(pkg_detail_info->pkgid, pkg_id.c_str(),
-      PKG_NAME_STRING_LEN_MAX - 1);
+          PKG_NAME_STRING_LEN_MAX - 1);
   if (app_data->Version() != NULL) {
     strncpy(pkg_detail_info->version, app_data->Version()->GetString().c_str(),
             PKG_VERSION_STRING_LEN_MAX - 1);
@@ -186,22 +186,22 @@ void PkgmgrBackendPlugin::SaveDetailInfo(
   std::string pkg_id = app_data->GetPackageID();
   if (force_type.empty())
     strncpy(pkg_detail_info->pkg_type,
-        xwalk::application::GetPackageType(pkg_id).c_str(),
-        PKG_TYPE_STRING_LEN_MAX - 1);
+            xwalk::application::GetPackageType(pkg_id).c_str(),
+            PKG_TYPE_STRING_LEN_MAX - 1);
   else  // force package type
     strncpy(pkg_detail_info->pkg_type,
-        force_type.c_str(),
-        PKG_TYPE_STRING_LEN_MAX - 1);
+            force_type.c_str(),
+            PKG_TYPE_STRING_LEN_MAX - 1);
   strncpy(pkg_detail_info->pkg_name, pkg_id.c_str(),
-      PKG_NAME_STRING_LEN_MAX - 1);
+          PKG_NAME_STRING_LEN_MAX - 1);
   strncpy(pkg_detail_info->pkgid, pkg_id.c_str(),
-      PKG_NAME_STRING_LEN_MAX - 1);
+          PKG_NAME_STRING_LEN_MAX - 1);
   if (app_data->Version() != NULL) {
     strncpy(pkg_detail_info->version, app_data->Version()->GetString().c_str(),
             PKG_VERSION_STRING_LEN_MAX - 1);
   }
   strncpy(pkg_detail_info->pkg_description, app_data->Description().c_str(),
-      PKG_VALUE_STRING_LEN_MAX - 1);
+          PKG_VALUE_STRING_LEN_MAX - 1);
 
   // xpk do not have this key in manifest
   if (app_data->manifest_type() == Manifest::TYPE_WIDGET) {
@@ -212,8 +212,8 @@ void PkgmgrBackendPlugin::SaveDetailInfo(
     DCHECK(tizen_app_info);
 
     strncpy(pkg_detail_info->min_platform_version,
-        tizen_app_info->required_version().c_str(),
-        PKG_VERSION_STRING_LEN_MAX -1);
+            tizen_app_info->required_version().c_str(),
+            PKG_VERSION_STRING_LEN_MAX -1);
   }
 
   pkg_detail_info->installed_time =
@@ -227,25 +227,25 @@ void PkgmgrBackendPlugin::SaveDetailInfo(
   pkg_detail_info->data_size = data_size;
 
   strncpy(pkg_detail_info->optional_id, app_data->GetPackageID().c_str(),
-      PKG_NAME_STRING_LEN_MAX - 1);
+          PKG_NAME_STRING_LEN_MAX - 1);
   pkg_detail_info->pkg_optional_info = NULL;
 }
 
 scoped_refptr<xwalk::application::ApplicationData>
 PkgmgrBackendPlugin::GetApplicationDataFromPkg(const std::string& pkg_path,
-    base::ScopedTempDir* dir) {
+                                               base::ScopedTempDir* dir) {
   base::FilePath unpacked_dir = dir->path();
-
   scoped_ptr<xwalk::application::Package> package =
       xwalk::application::Package::Create(base::FilePath(pkg_path));
   if (!package)
     return nullptr;
-  package->ExtractToTemporaryDir(&unpacked_dir);
-  std::string app_id = package->Id();
 
+  package->ExtractToTemporaryDir(&unpacked_dir);
   std::string error;
+  std::string app_id = package->Id();
   scoped_refptr<xwalk::application::ApplicationData> app_data = LoadApplication(
       unpacked_dir, app_id, xwalk::application::ApplicationData::TEMP_DIRECTORY,
       package->manifest_type(), &error);
+
   return app_data;
 }
index 8d6b203..d34d800 100644 (file)
@@ -6,8 +6,8 @@
 #define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_BACKEND_PLUGIN_H_
 
 #include <package-manager.h>
-#include <package-manager-types.h>
 #include <package-manager-plugin.h>
+#include <package-manager-types.h>
 
 #include <string>
 
index 7a26432..10a29cb 100644 (file)
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #include <package-manager.h>
-#include <package-manager-types.h>
 #include <package-manager-plugin.h>
+#include <package-manager-types.h>
 
 #include "base/logging.h"
 #include "xwalk/application/tools/tizen/xwalk_backend_plugin.h"
index 5fdb409..d95e2f6 100644 (file)
@@ -5,10 +5,11 @@
 
 #include "xwalk/application/tools/tizen/xwalk_package_installer.h"
 
-#include <sys/types.h>
 #include <pwd.h>
 #include <ss_manager.h>
+#include <sys/types.h>
 #include <unistd.h>
+
 #include <pkgmgr/pkgmgr_parser.h>
 
 #include <algorithm>
 #include "xwalk/application/common/permission_policy_manager.h"
 #include "xwalk/application/common/tizen/application_storage.h"
 #include "xwalk/application/common/tizen/encryption.h"
+#include "xwalk/application/common/tizen/package_query.h"
 #include "xwalk/application/tools/tizen/xwalk_packageinfo_constants.h"
 #include "xwalk/application/tools/tizen/xwalk_platform_installer.h"
+#include "xwalk/application/tools/tizen/xwalk_rds_delta_parser.h"
 #include "xwalk/runtime/common/xwalk_paths.h"
 
 namespace info = application_packageinfo_constants;
@@ -314,12 +317,11 @@ bool PackageInstaller::PlatformUpdate(ApplicationData* app_data) {
   return true;
 }
 
-bool PackageInstaller::PlatformReinstall(const base::FilePath& path) {
+bool PackageInstaller::PlatformReinstall(const std::string& pkgid) {
   PlatformInstaller platform_installer;
+  InitializePkgmgrSignal(&platform_installer, "-r", pkgid);
 
-  InitializePkgmgrSignal(&platform_installer, "-r", path.value());
-
-  return platform_installer.ReinstallApplication();
+  return platform_installer.ReinstallApplication(pkgid);
 }
 
 bool PackageInstaller::Install(const base::FilePath& path, std::string* id) {
@@ -620,8 +622,30 @@ bool PackageInstaller::Uninstall(const std::string& id) {
   return result;
 }
 
-bool PackageInstaller::Reinstall(const base::FilePath& path) {
-  return PlatformReinstall(path);
+bool PackageInstaller::Reinstall(const std::string& pkgid) {
+  base::FilePath app_dir = xwalk::application::GetPackagePath(pkgid);
+
+  if (!base::DirectoryExists(app_dir)) {
+    LOG(ERROR) << "Application directory " << app_dir.value()
+               << " does not exist!";
+    return false;
+  }
+
+  RDSDeltaParser rds_parser(app_dir, pkgid);
+  if (!rds_parser.Parse())
+    return false;
+
+  if (!rds_parser.ApplyParsedData())
+    return false;
+
+  if (!PlatformReinstall(pkgid)) {
+    LOG(ERROR) << "Reinstallation of package " << pkgid
+               << " has failed due to a platform error!";
+    return false;
+  }
+
+  LOG(INFO) << "Package " << pkgid << " has been reinstalled successfully";
+  return true;
 }
 
 void PackageInstaller::ContinueUnfinishedTasks() {
index 07c430d..117970d 100644 (file)
@@ -7,6 +7,7 @@
 #define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PACKAGE_INSTALLER_H_
 
 #include <string>
+
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 
@@ -24,14 +25,14 @@ class PlatformInstaller;
 class PackageInstaller {
  public:
   static scoped_ptr<PackageInstaller> Create(
-    xwalk::application::ApplicationStorage* storage);
+      xwalk::application::ApplicationStorage* storage);
 
   ~PackageInstaller();
 
   bool Install(const base::FilePath& path, std::string* id);
   bool Uninstall(const std::string& id);
   bool Update(const std::string& id, const base::FilePath& path);
-  bool Reinstall(const base::FilePath& path);
+  bool Reinstall(const std::string& pkgid);
 
   void ContinueUnfinishedTasks();
 
@@ -46,7 +47,7 @@ class PackageInstaller {
   bool PlatformInstall(xwalk::application::ApplicationData* data);
   bool PlatformUninstall(const std::string& app_id);
   bool PlatformUpdate(xwalk::application::ApplicationData* updated_data);
-  bool PlatformReinstall(const base::FilePath& path);
+  bool PlatformReinstall(const std::string& pkgid);
 
   xwalk::application::ApplicationStorage* storage_;
   bool quiet_;
index e712285..957ced7 100644 (file)
@@ -15,8 +15,8 @@ namespace application_packageinfo_constants {
   extern const base::FilePath::CharType kIconDir[];
   extern const base::FilePath::CharType kXmlDir[];
   extern const base::FilePath::CharType kXwalkPath[];
-
   extern const base::FilePath::CharType kExecDir[];
+
   extern const char kDefaultIconName[];
   extern const char kOwner[];
 
index f3079d9..7c5806c 100644 (file)
@@ -5,9 +5,9 @@
 #include "xwalk/application/tools/tizen/xwalk_platform_installer.h"
 
 #include <assert.h>
+#include <pkgmgr_installer.h>
 #include <pkgmgr/pkgmgr_parser.h>
 
-#include <pkgmgr_installer.h>
 // logging and dlog uses same macro name
 // to avoid warnings we need to undefine dlog's one
 #undef LOG
@@ -102,7 +102,7 @@ bool CopyFileToDst(const base::FilePath& file_src,
     base::CreateDirectory(dir);
   if (!base::CopyFile(file_src, file_dst)) {
     LOG(ERROR) << "Couldn't copy application file from "
-        << file_src.value() << " to " << file_dst.value();
+               << file_src.value() << " to " << file_dst.value();
     return false;
   }
   return true;
@@ -164,11 +164,11 @@ bool PlatformInstaller::UpdateApplication(const base::FilePath& xmlpath,
   return ret;
 }
 
-bool PlatformInstaller::ReinstallApplication() {
+bool PlatformInstaller::ReinstallApplication(const std::string& pkgid) {
   SendSignal(PKGMGR_START_KEY, PKGMGR_START_REINSTALL);
-  // FIXME not implemented, just send signal abotu failure
-  SendSignal(PKGMGR_END_KEY, ToEndStatus(false));
-  return false;
+  bool ret = ReinstallApplicationInternal(pkgid);
+  SendSignal(PKGMGR_END_KEY, ToEndStatus(ret));
+  return ret;
 }
 
 bool PlatformInstaller::InstallApplicationInternal(
@@ -203,17 +203,16 @@ bool PlatformInstaller::InstallApplicationInternal(
   LOG(INFO) << "UID of installation : " << uid;
   if (uid != GLOBAL_USER) {  // For only the user that request installation
     if (pkgmgr_parser_parse_usr_manifest_for_installation(
-        xmlpath.value().c_str(),
-        uid, const_cast<char**>(pkgmgr_tags))) {
+        xmlpath.value().c_str(), uid, const_cast<char**>(pkgmgr_tags))) {
       LOG(ERROR) << "Couldn't parse manifest XML '"
-          << xmlpath.value().c_str() << "', uid : " << uid;
+                 << xmlpath.value().c_str() << "', uid : " << uid;
       return false;
     }
   } else {  // For all users
-    if (pkgmgr_parser_parse_manifest_for_installation(xmlpath.value().c_str(),
-        const_cast<char**>(pkgmgr_tags))) {
+    if (pkgmgr_parser_parse_manifest_for_installation(
+        xmlpath.value().c_str(), const_cast<char**>(pkgmgr_tags))) {
       LOG(ERROR) << "Couldn't parse manifest XML '"
-          << xmlpath.value().c_str() << "' for global installation";
+                 << xmlpath.value().c_str() << "' for global installation";
       return false;
     }
   }
@@ -247,18 +246,18 @@ bool PlatformInstaller::UninstallApplicationInternal() {
   assert(!xmlpath_str.empty());
 
   if (uid != GLOBAL_USER) {  // For only the user that request installation
-    if (pkgmgr_parser_parse_usr_manifest_for_uninstallation(
-        xmlpath_str.c_str(), uid, NULL)) {
+    if (pkgmgr_parser_parse_usr_manifest_for_uninstallation(xmlpath_str.c_str(),
+        uid, NULL)) {
       LOG(ERROR) << "Couldn't parse manifest XML '" << xmlpath_str << "', uid"
-          << uid;
+                 << uid;
       icon_cleaner.Dismiss();
       xml_cleaner.Dismiss();
     }
   } else {  // For all users
-    if (pkgmgr_parser_parse_manifest_for_uninstallation(
-        xmlpath_str.c_str(), NULL)) {
+    if (pkgmgr_parser_parse_manifest_for_uninstallation(xmlpath_str.c_str(),
+        NULL)) {
       LOG(ERROR) << "Couldn't parse manifest XML '" << xmlpath_str
-          << "' for global uninstallation";
+                 << "' for global uninstallation";
       icon_cleaner.Dismiss();
       xml_cleaner.Dismiss();
     }
@@ -271,7 +270,6 @@ bool PlatformInstaller::UpdateApplicationInternal(
   if (xmlpath.empty() || iconpath.empty()) {
     LOG(ERROR) << "Invalid xml path or icon path for update";
   }
-
   base::FilePath global_xml(tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/"));
   base::FilePath global_icon(tzplatform_mkpath(TZ_SYS_RO_ICONS, kIconDir));
   base::FilePath user_xml(tzplatform_mkpath(TZ_USER_PACKAGES, "/"));
@@ -285,43 +283,46 @@ bool PlatformInstaller::UpdateApplicationInternal(
     xml = global_xml;
     icon = global_icon;
   }
-
   // FIXME(vcgomes): Add support for more icon types
   base::FilePath xml_dst = GetDestFilePath(xml, appid_, kXmlFileExt);
   base::FilePath icon_dst = GetDestFilePath(icon, appid_, kPngFileExt);
   FileDeleter xml_cleaner(xml_dst, false);
   FileDeleter icon_cleaner(icon_dst, false);
 
-
-  if (!CopyFileToDst(xmlpath, xml_dst)
-     || !CopyFileToDst(iconpath, icon_dst))
+  if (!CopyFileToDst(xmlpath, xml_dst) || !CopyFileToDst(iconpath, icon_dst))
     return false;
 
   if (uid != GLOBAL_USER) {  // For only the user that request installation
     if (pkgmgr_parser_parse_usr_manifest_for_upgrade(xmlpath.value().c_str(),
         uid, const_cast<char**>(pkgmgr_tags))) {
       LOG(ERROR) << "Couldn't parse manifest XML '" << xmlpath.value()
-          << "', uid: " << uid;
+                 << "', uid: " << uid;
       return false;
     }
   } else {  // For all users
     if (pkgmgr_parser_parse_manifest_for_upgrade(xmlpath.value().c_str(),
         const_cast<char**>(pkgmgr_tags))) {
       LOG(ERROR) << "Couldn't parse manifest XML '"
-          << xmlpath.value() << "' for global update installation";
+                 << xmlpath.value() << "' for global update installation";
       return false;
      }
   }
-
   xml_cleaner.Dismiss();
   icon_cleaner.Dismiss();
 
   return true;
 }
 
-bool PlatformInstaller::SendSignal(
-    const std::string& key,
-    const std::string& value) {
+bool PlatformInstaller::ReinstallApplicationInternal(const std::string& pkgid) {
+  if (pkgid.empty()) {
+    LOG(ERROR) << "Invalid package ID for reinstallation!";
+    return false;
+  }
+  return true;
+}
+
+bool PlatformInstaller::SendSignal(const std::string& key,
+                                   const std::string& value) {
   if (!handle_) {
     // this is installation with xwalkctl not pkgmgr
     return true;
@@ -332,11 +333,9 @@ bool PlatformInstaller::SendSignal(
     return false;
   }
 
-  if (pkgmgr_installer_send_signal(
-          handle_, PKGMGR_PKG_TYPE, pkgid_.c_str(),
-          key.c_str(), value.c_str())) {
+  if (pkgmgr_installer_send_signal(handle_, PKGMGR_PKG_TYPE, pkgid_.c_str(),
+      key.c_str(), value.c_str())) {
     LOG(ERROR) << "Fail to send package manager signal";
   }
-
   return true;
 }
index 31e175a..ad28aa3 100644 (file)
@@ -23,7 +23,7 @@ class PlatformInstaller {
   bool UninstallApplication();
   bool UpdateApplication(const base::FilePath& xmlpath,
                          const base::FilePath& iconpath);
-  bool ReinstallApplication();
+  bool ReinstallApplication(const std::string& pkgid);
 
  private:
   bool InstallApplicationInternal(const base::FilePath& xmlpath,
@@ -31,6 +31,7 @@ class PlatformInstaller {
   bool UninstallApplicationInternal();
   bool UpdateApplicationInternal(const base::FilePath& xmlpath,
                                  const base::FilePath& iconpath);
+  bool ReinstallApplicationInternal(const std::string& pkgid);
 
   bool SendSignal(const std::string& key, const std::string& value);
 
diff --git a/src/xwalk/application/tools/tizen/xwalk_rds_delta_parser.cc b/src/xwalk/application/tools/tizen/xwalk_rds_delta_parser.cc
new file mode 100644 (file)
index 0000000..3f9e43a
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/application/tools/tizen/xwalk_rds_delta_parser.h"
+
+#include <list>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/strings/string_split.h"
+
+namespace {
+
+const char kRDSDeltaFile[] = ".rds_delta";
+const std::string kRDSWidgetPath = "res/wgt/";
+const std::string kKeyAdd = "#add";
+const std::string kKeyDelete = "#delete";
+const std::string kKeyModify = "#modify";
+const base::FilePath kRDSTempDir = base::FilePath("/opt/usr/apps/tmp/");
+const std::list<std::string> key_list = {kKeyDelete, kKeyAdd, kKeyModify};
+
+}  // namespace
+
+RDSDeltaParser::RDSDeltaParser(const base::FilePath& app_path,
+    const std::string& pkgid) : app_dir_(app_path) {
+  rds_dir_ = kRDSTempDir.Append(pkgid);
+}
+
+bool RDSDeltaParser::Parse() {
+  base::FilePath rds_file = rds_dir_.AppendASCII(kRDSDeltaFile);
+
+  if (!base::PathExists(rds_file)) {
+    LOG(ERROR) << "RDS delta file " << rds_file.value()
+               << " does not exists!";
+    return false;
+  }
+
+  std::string file_buffer;
+  if (!base::ReadFileToString(rds_file, &file_buffer)) {
+    LOG(ERROR) << "RDS delta file " << rds_file.value()
+               << " cannot be read!";
+    return false;
+  }
+
+  std::vector<std::string> lines;
+  base::SplitString(file_buffer, '\n', &lines);
+
+  if (lines.empty()) {
+    LOG(ERROR) << "RDS delta file " << rds_file.value() << " is empty!";
+    return false;
+  }
+
+  std::string key;
+  parsed_data_.clear();
+  for (const auto& line : lines) {
+    for (const auto& it : key_list) {
+      if (line == it) {
+        key = line;
+        break;
+      }
+    }
+    if (key == line || line.empty() || line == "\n") {
+      continue;
+    }
+    parsed_data_.insert(std::pair<std::string, std::string>(key,
+        line.substr(kRDSWidgetPath.length())));
+  }
+  return true;
+}
+
+bool RDSDeltaParser::ApplyParsedData() {
+  for (const auto& it : parsed_data_) {
+    if (it.first == kKeyDelete)
+      return DeleteFile(it.second);
+    if (it.first == kKeyAdd)
+      return AddFile(it.second);
+    if (it.first == kKeyModify)
+      return ModifyFile(it.second);
+  }
+  return true;
+}
+
+bool RDSDeltaParser::AddFile(const std::string& file_name) {
+  base::FilePath src_path = rds_dir_.Append(kRDSWidgetPath).Append(file_name);
+
+  if (!base::PathExists(src_path)) {
+    LOG(ERROR) << "File " << src_path.value() << " does not exists!";
+    return false;
+  }
+  base::FilePath dst_file = app_dir_.Append(file_name);
+  if (!base::DirectoryExists(dst_file.DirName()) &&
+      !base::CreateDirectory(dst_file.DirName())) {
+    LOG(ERROR) << "Can't create directory " << dst_file.DirName().value();
+    return false;
+  }
+  if (!base::CopyFile(src_path, dst_file)) {
+    LOG(ERROR) << "Error when adding a file " << src_path.BaseName().value()
+               << " to " << dst_file.DirName().value();
+    return false;
+  }
+  return true;
+}
+
+bool RDSDeltaParser::DeleteFile(const std::string& file_name) {
+  base::FilePath dst_file = app_dir_.Append(file_name);
+
+  if (!base::DeleteFile(dst_file, true)) {
+    LOG(ERROR) << "Error when deleting a file " << dst_file.value();
+    return false;
+  }
+  return true;
+}
+
+bool RDSDeltaParser::ModifyFile(const std::string& file_name) {
+  base::FilePath src_file = rds_dir_.Append(kRDSWidgetPath).Append(file_name);
+
+  if (!base::PathExists(src_file)) {
+    LOG(ERROR) << "File " << src_file.value() << " does not exists!";
+    return false;
+  }
+
+  base::FilePath dst_file = app_dir_.Append(file_name);
+  if (!base::CopyFile(src_file, dst_file)) {
+    LOG(ERROR) << "Error when copying a file " << src_file.value()
+               << " to " << dst_file.DirName().value();
+    return false;
+  }
+  return true;
+}
diff --git a/src/xwalk/application/tools/tizen/xwalk_rds_delta_parser.h b/src/xwalk/application/tools/tizen/xwalk_rds_delta_parser.h
new file mode 100644 (file)
index 0000000..2d28dbd
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_APPLICATION_TOOLS_TIZEN_XWALK_RDS_DELTA_PARSER_H_
+#define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_RDS_DELTA_PARSER_H_
+
+#include <map>
+#include <string>
+
+#include "base/files/file_path.h"
+
+class RDSDeltaParser {
+ public:
+  RDSDeltaParser(const base::FilePath& app_path, const std::string& pkgid);
+  bool Parse();
+  bool ApplyParsedData();
+
+ private:
+  base::FilePath app_dir_;
+  base::FilePath rds_dir_;
+  std::multimap<std::string, std::string> parsed_data_;
+
+  bool AddFile(const std::string& file_name);
+  bool DeleteFile(const std::string& file_name);
+  bool ModifyFile(const std::string& file_name);
+};
+
+#endif  // XWALK_APPLICATION_TOOLS_TIZEN_XWALK_RDS_DELTA_PARSER_H_
index 72b5668..f7e7ef5 100644 (file)
@@ -20,6 +20,8 @@
         'xwalk_packageinfo_constants.h',
         'xwalk_platform_installer.cc',
         'xwalk_platform_installer.h',
+        'xwalk_rds_delta_parser.cc',
+        'xwalk_rds_delta_parser.h',
         'xwalk_tizen_user.cc',
         'xwalk_tizen_user.h',
         # TODO(t.iwanek) fix me - this duplicates compilation of those files
index f02e61f..43436ac 100644 (file)
@@ -2,15 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <unistd.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
+#include "xwalk/application/tools/tizen/xwalk_tizen_user.h"
+
 #include <errno.h>
-#include <pwd.h>
 #include <grp.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 #include <tzplatform_config.h>
 
 int xwalk_tizen_check_user_app(void) {
@@ -27,20 +30,19 @@ int xwalk_tizen_check_user_app(void) {
 
   err = getgrgid_r(getgid(), &grp, buffer, len, &current_g);
   if (err) {
-  fprintf(stderr, "group can't be determined");
+    fprintf(stderr, "group can't be determined");
+    fprintf(stderr, "launching an application will not work\n");
+    free(buffer);
+    return -EINVAL;
+  }
+  if ((!current_g) ||
+      (strcmp(current_g->gr_name, "users") &&
+       strcmp(current_g->gr_name, "app"))) {
+    fprintf(stderr, "group '%s' is not allowed :",
+            current_g ? current_g->gr_name : "<NULL>");
     fprintf(stderr, "launching an application will not work\n");
     free(buffer);
     return -EINVAL;
-  } else {
-    if ( (!current_g) || (
-        strcmp(current_g->gr_name, "users") &&
-        strcmp(current_g->gr_name, "app") )) {
-      fprintf(stderr, "group '%s' is not allowed :",
-          current_g ? current_g->gr_name : "<NULL>");
-      fprintf(stderr, "launching an application will not work\n");
-      free(buffer);
-      return -EINVAL;
-    }
   }
   return 0;
 }
@@ -59,22 +61,21 @@ int xwalk_tizen_check_user_for_xwalkctl(void) {
 
   err = getgrgid_r(getgid(), &grp, buffer, len, &current_g);
   if (err) {
-  fprintf(stderr, "group can't be determined");
+    fprintf(stderr, "group can't be determined");
     fprintf(stderr, "launching an application will not work\n");
     free(buffer);
     return -EINVAL;
-  } else {
-    if ( (!current_g) || (
-        strcmp(current_g->gr_name, "users") &&
-        strcmp(current_g->gr_name, "app") &&
-        (strcmp(current_g->gr_name, "root") &&
-         getuid() == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)))) {
-      fprintf(stderr, "group '%s' is not allowed :",
+  }
+  if ((!current_g) ||
+      (strcmp(current_g->gr_name, "users") &&
+       strcmp(current_g->gr_name, "app") &&
+      (strcmp(current_g->gr_name, "root") &&
+       getuid() == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)))) {
+    fprintf(stderr, "group '%s' is not allowed :",
             current_g ? current_g->gr_name : "<NULL>");
-      fprintf(stderr, "launching an application will not work\n");
-      free(buffer);
-      return -EINVAL;
-    }
+    fprintf(stderr, "launching an application will not work\n");
+    free(buffer);
+    return -EINVAL;
   }
   return 0;
 }
index 5941771..fd03fd5 100644 (file)
@@ -269,6 +269,8 @@ void XWalkExtensionProcessHost::OnRenderChannelCreated(
   is_extension_process_channel_ready_ = true;
   ep_rp_channel_handle_ = handle;
   ReplyChannelHandleToRenderProcess();
+  if (delegate_)
+    delegate_->OnRenderChannelCreated(render_process_host_->GetID());
 }
 
 void XWalkExtensionProcessHost::ReplyChannelHandleToRenderProcess() {
index cc18f9f..588763f 100644 (file)
@@ -45,6 +45,8 @@ class XWalkExtensionProcessHost
     virtual bool OnRegisterPermissions(int render_process_id,
                                        const std::string& extension_name,
                                        const std::string& perm_table);
+    virtual void OnRenderChannelCreated(int render_process_id) {}
+
    protected:
     ~Delegate() {}
   };
index 13df657..a74c3c3 100644 (file)
@@ -479,5 +479,10 @@ bool XWalkExtensionService::OnRegisterPermissions(
                                         extension_name, perm_table);
 }
 
+void XWalkExtensionService::OnRenderChannelCreated(int render_process_id) {
+  CHECK(delegate_);
+  delegate_->RenderChannelCreated(render_process_id);
+}
+
 }  // namespace extensions
 }  // namespace xwalk
index 9141449..6e856e1 100644 (file)
@@ -51,6 +51,7 @@ class XWalkExtensionService : public content::NotificationObserver,
     virtual void ExtensionProcessCreated(
         int render_process_id,
         const IPC::ChannelHandle& channel_handle) {}
+    virtual void RenderChannelCreated(int render_process_id) {}
 
    protected:
     ~Delegate() {}
@@ -103,6 +104,7 @@ class XWalkExtensionService : public content::NotificationObserver,
   virtual void OnExtensionProcessCreated(
       int render_process_id,
       const IPC::ChannelHandle handle) OVERRIDE;
+  virtual void OnRenderChannelCreated(int render_process_id) OVERRIDE;
 
   virtual void OnCheckAPIAccessControl(
       int render_process_id,
index f7eea33..69b5b03 100644 (file)
@@ -219,7 +219,7 @@ static jlong GetOrCreateExtension(JNIEnv* env, jobject obj, jstring name,
 }
 
 bool RegisterXWalkExtensionAndroid(JNIEnv* env) {
-  return RegisterNativesImpl(env) >= 0;
+  return RegisterNativesImpl(env);
 }
 
 }  // namespace extensions
index f554653..4c86808 100644 (file)
@@ -16,6 +16,21 @@ using xwalk::NativeAppWindow;
 using xwalk::Runtime;
 using xwalk::extensions::XWalkExtensionVector;
 
+namespace {
+Runtime* CreateWithDefaultWindow(
+    xwalk::RuntimeContext* runtime_context, const GURL& url,
+    Runtime::Observer* observer = NULL) {
+  Runtime* runtime = Runtime::Create(runtime_context, observer);
+  runtime->LoadURL(url);
+#if !defined(OS_ANDROID)
+  xwalk::RuntimeUIStrategy ui_strategy;
+  xwalk::NativeAppWindow::CreateParams params;
+  ui_strategy.Show(runtime, params);
+#endif
+  return runtime;
+}
+}  // namespace
+
 class ExternalExtensionMultiProcessTest : public XWalkExtensionsTestBase {
  public:
   ExternalExtensionMultiProcessTest()
@@ -124,7 +139,7 @@ IN_PROC_BROWSER_TEST_F(ExternalExtensionMultiProcessTest,
   WaitForLoadStop(runtime()->web_contents());
   EXPECT_EQ(1, CountRegisterExtensions());
 
-  Runtime* new_runtime = Runtime::CreateWithDefaultWindow(
+  Runtime* new_runtime = CreateWithDefaultWindow(
       GetRuntimeContext(), url, runtime_registry());
   EXPECT_EQ(new_runtime, WaitForSingleNewRuntime());
   EXPECT_NE(runtime(), new_runtime);
index 7420b6f..f3c1764 100644 (file)
@@ -24,7 +24,7 @@
 %define _binary_payload w3.gzdio
 
 Name:           crosswalk
-Version:        10.39.234.0
+Version:        11.39.244.0
 Release:        0
 Summary:        Chromium-based app runtime
 License:        (BSD-3-Clause and LGPL-2.1+)
@@ -53,6 +53,7 @@ BuildRequires:  python
 BuildRequires:  python-xml
 BuildRequires:  perl
 BuildRequires:  which
+BuildRequires:  yasm
 BuildRequires:  pkgconfig(ail)
 BuildRequires:  pkgconfig(alsa)
 BuildRequires:  pkgconfig(appcore-common)
@@ -242,6 +243,7 @@ ${GYP_EXTRA_FLAGS} \
 -Duse_system_libexif=1 \
 -Duse_system_libxml=1 \
 -Duse_system_nspr=1 \
+-Duse_system_yasm=1 \
 -Dshared_process_mode=1 \
 -Denable_hidpi=1
 
index a8e082d..4a1d043 100644 (file)
@@ -188,6 +188,8 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public void supplyContentsForPopup(XWalkContent newContents) {
+        if (mNativeContent == 0) return;
+
         long popupNativeXWalkContent = nativeReleasePopupXWalkContent(mNativeContent);
         if (popupNativeXWalkContent == 0) {
             Log.w(TAG, "Popup XWalkView bind failed: no pending content.");
@@ -229,6 +231,8 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public void loadUrl(String url, String data) {
+        if (mNativeContent == 0) return;
+
         if ((url == null || url.isEmpty()) &&
                 (data == null || data.isEmpty())) {
             return;
@@ -238,6 +242,8 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public void reload(int mode) {
+        if (mNativeContent == 0) return;
+
         switch (mode) {
             case XWalkViewInternal.RELOAD_IGNORE_CACHE:
                 mNavigationController.reloadIgnoringCache(true);
@@ -249,23 +255,27 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public String getUrl() {
+        if (mNativeContent == 0) return null;
         String url = mWebContents.getUrl();
         if (url == null || url.trim().isEmpty()) return null;
         return url;
     }
 
     public String getTitle() {
+        if (mNativeContent == 0) return null;
         String title = mWebContents.getTitle().trim();
         if (title == null) title = "";
         return title;
     }
 
     public void addJavascriptInterface(Object object, String name) {
+        if (mNativeContent == 0) return;
         mContentViewCore.addPossiblyUnsafeJavascriptInterface(object, name,
                 javascriptInterfaceClass);
     }
 
     public void evaluateJavascript(String script, ValueCallback<String> callback) {
+        if (mNativeContent == 0) return;
         final ValueCallback<String>  fCallback = callback;
         JavaScriptCallback coreCallback = null;
         if (fCallback != null) {
@@ -280,50 +290,62 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public void setUIClient(XWalkUIClientInternal client) {
+        if (mNativeContent == 0) return;
         mContentsClientBridge.setUIClient(client);
     }
 
     public void setResourceClient(XWalkResourceClientInternal client) {
+        if (mNativeContent == 0) return;
         mContentsClientBridge.setResourceClient(client);
     }
 
     public void setXWalkWebChromeClient(XWalkWebChromeClient client) {
+        if (mNativeContent == 0) return;
         mContentsClientBridge.setXWalkWebChromeClient(client);
     }
 
     public XWalkWebChromeClient getXWalkWebChromeClient() {
+        if (mNativeContent == 0) return null;
         return mContentsClientBridge.getXWalkWebChromeClient();
     }
 
     public void setXWalkClient(XWalkClient client) {
+        if (mNativeContent == 0) return;
         mContentsClientBridge.setXWalkClient(client);
     }
 
     public void setDownloadListener(DownloadListener listener) {
+        if (mNativeContent == 0) return;
         mContentsClientBridge.setDownloadListener(listener);
     }
 
     public void setNavigationHandler(XWalkNavigationHandler handler) {
+        if (mNativeContent == 0) return;
         mContentsClientBridge.setNavigationHandler(handler);
     }
 
     public void setNotificationService(XWalkNotificationService service) {
+        if (mNativeContent == 0) return;
         mContentsClientBridge.setNotificationService(service);
     }
 
     public void onPause() {
+        if (mNativeContent == 0) return;
         mContentViewCore.onHide();
     }
 
     public void onResume() {
+        if (mNativeContent == 0) return;
         mContentViewCore.onShow();
     }
 
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (mNativeContent == 0) return;
         mWindow.onActivityResult(requestCode, resultCode, data);
     }
 
     public boolean onNewIntent(Intent intent) {
+        if (mNativeContent == 0) return false;
         return mContentsClientBridge.onNewIntent(intent);
     }
 
@@ -333,22 +355,25 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public void clearHistory() {
+        if (mNativeContent == 0) return;
         mNavigationController.clearHistory();
     }
 
     public boolean canGoBack() {
-        return mNavigationController.canGoBack();
+        return (mNativeContent == 0) ? false : mNavigationController.canGoBack();
     }
 
     public void goBack() {
+        if (mNativeContent == 0) return;
         mNavigationController.goBack();
     }
 
     public boolean canGoForward() {
-        return mNavigationController.canGoForward();
+        return (mNativeContent == 0) ? false : mNavigationController.canGoForward();
     }
 
     public void goForward() {
+        if (mNativeContent == 0) return;
         mNavigationController.goForward();
     }
 
@@ -357,6 +382,7 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public void stopLoading() {
+        if (mNativeContent == 0) return;
         mWebContents.stop();
         mContentsClientBridge.onStopLoading();
     }
@@ -371,18 +397,19 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     // details in content_view_statics.cc.
     // We need follow up after upstream updates that.
     public void pauseTimers() {
-        if (timerPaused) return;
+        if (timerPaused || (mNativeContent == 0)) return;
         ContentViewStatics.setWebKitSharedTimersSuspended(true);
         timerPaused = true;
     }
 
     public void resumeTimers() {
-        if (!timerPaused) return;
+        if (!timerPaused || (mNativeContent == 0)) return;
         ContentViewStatics.setWebKitSharedTimersSuspended(false);
         timerPaused = false;
     }
 
     public String getOriginalUrl() {
+        if (mNativeContent == 0) return null;
         NavigationHistory history = mNavigationController.getNavigationHistory();
         int currentIndex = history.getCurrentEntryIndex();
         if (currentIndex >= 0 && currentIndex < history.getEntryCount()) {
@@ -396,6 +423,11 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
         return nativeGetVersion(mNativeContent);
     }
 
+    public void setBackgroundColor(int color) {
+        if (mNativeContent == 0) return;
+        nativeSetBackgroundColor(mNativeContent, color);
+    }
+
     public void setNetworkAvailable(boolean networkUp) {
         if (mNativeContent == 0) return;
         nativeSetJsOnlineProperty(mNativeContent, networkUp);
@@ -408,6 +440,7 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
 
     // For instrumentation test.
     public void installWebContentsObserverForTest(XWalkContentsClient contentClient) {
+        if (mNativeContent == 0) return;
         contentClient.installWebContentsObserver(mContentViewCore.getWebContents());
     }
 
@@ -454,13 +487,15 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public XWalkNavigationHistoryInternal getNavigationHistory() {
+        if (mNativeContent == 0) return null;
+
         return new XWalkNavigationHistoryInternal(mXWalkView, mNavigationController.getNavigationHistory());
     }
 
     public static final String SAVE_RESTORE_STATE_KEY = "XWALKVIEW_STATE";
 
     public XWalkNavigationHistoryInternal saveState(Bundle outState) {
-        if (outState == null) return null;
+        if (mNativeContent == 0 || outState == null) return null;
 
         byte[] state = nativeGetState(mNativeContent);
         if (state == null) return null;
@@ -470,7 +505,7 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
     }
 
     public XWalkNavigationHistoryInternal restoreState(Bundle inState) {
-        if (inState == null) return null;
+        if (mNativeContent == 0 || inState == null) return null;
 
         byte[] state = inState.getByteArray(SAVE_RESTORE_STATE_KEY);
         if (state == null) return null;
@@ -641,6 +676,7 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
 
     @CalledByNative
     private void onGeolocationPermissionsShowPrompt(String origin) {
+        if (mNativeContent == 0) return;
         // Reject if geolocation is disabled, or the origin has a retained deny.
         if (!mSettings.getGeolocationEnabled()) {
             nativeInvokeGeolocationCallback(mNativeContent, false, origin);
@@ -662,23 +698,17 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
         mContentsClientBridge.onGeolocationPermissionsHidePrompt();
     }
 
-    public void enableRemoteDebugging(int allowedUid) {
+    public void enableRemoteDebugging() {
         // Chrome looks for "devtools_remote" pattern in the name of a unix domain socket
         // to identify a debugging page
         final String socketName = getContext().getApplicationContext().getPackageName() + "_devtools_remote";
         if (mDevToolsServer == null) {
             mDevToolsServer = new XWalkDevToolsServer(socketName);
-            mDevToolsServer.allowConnectionFromUid(allowedUid);
-            mDevToolsServer.setRemoteDebuggingEnabled(true);
+            mDevToolsServer.setRemoteDebuggingEnabled(
+                    true, XWalkDevToolsServer.Security.ALLOW_SOCKET_ACCESS);
         }
     }
 
-    // Enables remote debugging and returns the URL at which the dev tools server is listening
-    // for commands. Only the current process is allowed to connect to the server.
-    void enableRemoteDebugging() {
-        enableRemoteDebugging(getContext().getApplicationInfo().uid);
-    }
-
     void disableRemoteDebugging() {
         if (mDevToolsServer ==  null) return;
 
@@ -747,4 +777,5 @@ class XWalkContent extends FrameLayout implements XWalkPreferencesInternal.KeyVa
             long nativeXWalkContent, boolean value, String requestingFrame);
     private native byte[] nativeGetState(long nativeXWalkContent);
     private native boolean nativeSetState(long nativeXWalkContent, byte[] state);
+    private native void nativeSetBackgroundColor(long nativeXWalkContent, int color);
 }
index e33d52b..aebad33 100644 (file)
@@ -515,11 +515,11 @@ class XWalkContentsClientBridge extends XWalkContentsClient
                 if (completed) {
                     throw new IllegalStateException("Duplicate openFileChooser result");
                 }
-                completed = true;
                 if (value == null && !syncCallFinished) {
                     syncNullReceived = true;
                     return;
                 }
+                completed = true;
                 if (value == null) {
                     nativeOnFilesNotSelected(mNativeContentsClientBridge,
                             processId, renderId, modeFlags);
@@ -549,6 +549,9 @@ class XWalkContentsClientBridge extends XWalkContentsClient
         // File chooser requires user interaction, valid derives should handle it in async process.
         // If the ValueCallback receive a sync result with null value, it is considered the
         // file chooser is not overridden.
+        if (uploadFile.syncNullReceived) {
+            return mXWalkView.showFileChooser(uploadFile, acceptTypes, Boolean.toString(capture));
+        }
         return !uploadFile.syncNullReceived;
     }
 
index cd33954..c5dcb1c 100644 (file)
@@ -27,6 +27,9 @@ class XWalkDevToolsServer {
         // In addition to default authorization allows access to an app with android permission
         // named chromeAppPackageName + DEBUG_PERMISSION_SUFFIX.
         ALLOW_DEBUG_PERMISSION,
+
+        // Allow other apps to access the web socket url to remote debug.
+        ALLOW_SOCKET_ACCESS,
     }
 
     public XWalkDevToolsServer(String socketName) {
@@ -45,17 +48,15 @@ class XWalkDevToolsServer {
 
     public void setRemoteDebuggingEnabled(boolean enabled, Security security) {
         boolean allowDebugPermission = security == Security.ALLOW_DEBUG_PERMISSION;
-        nativeSetRemoteDebuggingEnabled(mNativeDevToolsServer, enabled, allowDebugPermission);
+        boolean allowSocketAccess = security == Security.ALLOW_SOCKET_ACCESS;
+        nativeSetRemoteDebuggingEnabled(
+                mNativeDevToolsServer, enabled, allowDebugPermission, allowSocketAccess);
     }
 
     public void setRemoteDebuggingEnabled(boolean enabled) {
         setRemoteDebuggingEnabled(enabled, Security.DEFAULT);
     }
 
-    public void allowConnectionFromUid(int uid) {
-        nativeAllowConnectionFromUid(mNativeDevToolsServer, uid);
-    }
-
     public String getSocketName() {
         return mSocketName;
     }
@@ -64,8 +65,7 @@ class XWalkDevToolsServer {
     private native void nativeDestroyRemoteDebugging(long devToolsServer);
     private native boolean nativeIsRemoteDebuggingEnabled(long devToolsServer);
     private native void nativeSetRemoteDebuggingEnabled(
-            long devToolsServer, boolean enabled, boolean allowDebugPermission);
-    private native void nativeAllowConnectionFromUid(long devToolsServer, int uid);
+            long devToolsServer, boolean enabled, boolean allowDebugPermission, boolean allowSocketAccess);
 
     @CalledByNative
     private static boolean checkDebugPermission(Context context, int pid, int uid) {
index 381daaa..f199e88 100644 (file)
@@ -223,8 +223,8 @@ public class XWalkResourceClientInternal {
 
     /**
       * Notify the host application that an SSL error occurred while loading a
-      * resource. The host application must call either callback.onReceivedValue(true)
-      * or callback.onReceivedValue(false) . Note that the decision may be retained for
+      * resource. The host application must call either callback.onReceiveValue(true)
+      * or callback.onReceiveValue(false) . Note that the decision may be retained for
       * use in response to future SSL errors. The default behavior is to pop up a dialog
       * @param view the xwalkview that is initiating the callback
       * @param callback passing 'true' means accepting the ssl error and continue to load.
index f57dc48..e686621 100644 (file)
@@ -10,23 +10,28 @@ import android.app.ApplicationErrorReport;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.graphics.Paint;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Looper;
+import android.provider.MediaStore;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.ViewGroup;
 import android.webkit.ValueCallback;
 import android.widget.FrameLayout;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.ref.WeakReference;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
@@ -147,12 +152,16 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
     }
 
     static final String PLAYSTORE_DETAIL_URI = "market://details?id=";
+    public static final int INPUT_FILE_REQUEST_CODE = 1;
+    private static final String TAG = XWalkViewInternal.class.getSimpleName();
 
     private XWalkContent mContent;
     private Activity mActivity;
     private Context mContext;
     private boolean mIsHidden;
     private XWalkActivityStateListener mActivityStateListener;
+    private ValueCallback<Uri> mFilePathCallback;
+    private String mCameraPhotoPath;
 
     /**
      * Normal reload mode as default.
@@ -653,6 +662,28 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
     @XWalkAPI
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (mContent == null) return;
+        if(requestCode == INPUT_FILE_REQUEST_CODE && mFilePathCallback != null) {
+            Uri results = null;
+
+            // Check that the response is a good one
+            if(Activity.RESULT_OK == resultCode) {
+                if(data == null) {
+                    // If there is not data, then we may have taken a photo
+                    if(mCameraPhotoPath != null) {
+                        results = Uri.parse(mCameraPhotoPath);
+                    }
+                } else {
+                    String dataString = data.getDataString();
+                    if (dataString != null) {
+                        results = Uri.parse(dataString);
+                    }
+                }
+            }
+
+            mFilePathCallback.onReceiveValue(results);
+            mFilePathCallback = null;
+            return;
+        }
         mContent.onActivityResult(requestCode, resultCode, data);
     }
 
@@ -704,7 +735,7 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
     // TODO(yongsheng): make it static?
     @XWalkAPI
     public String getAPIVersion() {
-        return "3.0";
+        return "4.1";
     }
 
     /**
@@ -745,6 +776,30 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
         mContent.setResourceClient(client);
     }
 
+    /**
+     * Set Background color of the view
+     */
+    @Override
+    @XWalkAPI
+    public void setBackgroundColor(int color) {
+        if (mContent == null) return;
+        checkThreadSafety();
+        mContent.setBackgroundColor(color);
+    }
+
+    /**
+     * override setLayerType
+     */
+    @Override
+    @XWalkAPI
+    public void setLayerType(int layerType, Paint paint) {
+        if (layerType != LAYER_TYPE_SOFTWARE) {
+           super.setLayerType(layerType, paint);
+        } else {
+            Log.w(TAG, "LAYER_TYPE_SOFTWARE is not supported by XwalkView");
+        }
+    }
+
     // TODO(yongsheng): this is not public.
     /**
      * @hide
@@ -771,33 +826,27 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
     /**
      * Enables remote debugging and returns the URL at which the dev tools
      * server is listening for commands.
-     * The allowedUid argument can be used to specify the uid of the process
-     * that is permitted to connect.
      */
-    public void enableRemoteDebugging(int allowedUid) {
+    public void enableRemoteDebugging() {
         if (mContent == null) return;
         checkThreadSafety();
-        mContent.enableRemoteDebugging(allowedUid);
+        mContent.enableRemoteDebugging();
     }
 
     /**
      * Get the websocket url for remote debugging.
      * @return the web socket url to remote debug this xwalk view.
      * null will be returned if remote debugging is not enabled.
-     * @since 4.0
+     * @since 4.1
      */
     @XWalkAPI
-    public URL getRemoteDebuggingUrl() {
+    public Uri getRemoteDebuggingUrl() {
         if (mContent == null) return null;
         checkThreadSafety();
         String wsUrl = mContent.getRemoteDebuggingUrl();
         if (wsUrl == null || wsUrl.isEmpty()) return null;
 
-        try {
-            return new URL(wsUrl);
-        } catch (MalformedURLException e) {
-            return null;
-        }
+        return Uri.parse(wsUrl);
     }
 
     /**
@@ -847,12 +896,6 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
         disableRemoteDebugging();
     }
 
-    // Enables remote debugging and returns the URL at which the dev tools server is listening
-    // for commands. Only the current process is allowed to connect to the server.
-    void enableRemoteDebugging() {
-        enableRemoteDebugging(mContext.getApplicationInfo().uid);
-    }
-
     void disableRemoteDebugging() {
         if (mContent == null) return;
         checkThreadSafety();
@@ -973,4 +1016,75 @@ public class XWalkViewInternal extends android.widget.FrameLayout {
                 break;
         }
     }
+
+    /**
+     * Tell the client to show a file chooser.
+     * @param uploadFile the callback class to handle the result from caller. It MUST
+     *        be invoked in all cases. Leave it not invoked will block all following
+     *        requests to open file chooser.
+     * @param acceptType value of the 'accept' attribute of the input tag associated
+     *        with this file picker.
+     * @param capture value of the 'capture' attribute of the input tag associated
+     *        with this file picker
+     */
+    public boolean showFileChooser(ValueCallback<Uri> uploadFile, String acceptType,
+            String capture) {
+        mFilePathCallback = uploadFile;
+
+        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+        if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
+            // Create the File where the photo should go
+            File photoFile = null;
+            try {
+                photoFile = createImageFile();
+                takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
+            } catch (IOException ex) {
+                // Error occurred while creating the File
+                Log.e(TAG, "Unable to create Image File", ex);
+            }
+
+            // Continue only if the File was successfully created
+            if (photoFile != null) {
+                mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
+                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
+                        Uri.fromFile(photoFile));
+            } else {
+                takePictureIntent = null;
+            }
+        }
+
+        Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
+        contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
+        contentSelectionIntent.setType("*/*");
+
+        Intent camcorder = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+        Intent soundRecorder = new Intent(
+                MediaStore.Audio.Media.RECORD_SOUND_ACTION);
+        ArrayList<Intent> extraIntents = new ArrayList<Intent>();
+        extraIntents.add(takePictureIntent);
+        extraIntents.add(camcorder);
+        extraIntents.add(soundRecorder);
+
+        Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
+        chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
+        chooserIntent.putExtra(Intent.EXTRA_TITLE, "Choose an action");
+        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
+                extraIntents.toArray(new Intent[] { }));
+        getActivity().startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
+        return true;
+    }
+
+    private File createImageFile() throws IOException {
+        // Create an image file name
+        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+        String imageFileName = "JPEG_" + timeStamp + "_";
+        File storageDir = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_PICTURES);
+        File imageFile = File.createTempFile(
+                imageFileName,  /* prefix */
+                ".jpg",         /* suffix */
+                storageDir      /* directory */
+        );
+        return imageFile;
+    }
 }
index 0a2d61e..07e3902 100644 (file)
@@ -22,6 +22,7 @@ import android.util.Log;
 import java.lang.ref.WeakReference;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.UUID;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -34,11 +35,13 @@ public class MessagingSmsManager {
     private final static String EXTRA_MSGTEXT = "message";
     private final static String EXTRA_MSGTO = "to";
     private final static String EXTRA_MSGINSTANCEID = "instanceid";
+    private final static String EXTRA_UUID= "UUID";
     private final static String DEFAULT_SERVICE_ID = "sim0";
     private final WeakReference<Activity> mActivity;
     private final Messaging mMessagingHandler;
     private BroadcastReceiver mSmsSentReceiver, mSmsDeliveredReceiver,
                               mSmsReceiveReceiver, mSmsServiceReceiver;
+    private String mUUID;
 
     private abstract class MessagingReceiver extends BroadcastReceiver {
         protected Messaging mMessaging;
@@ -51,6 +54,7 @@ public class MessagingSmsManager {
     MessagingSmsManager(Activity activity, Messaging messaging) {
         mActivity = new WeakReference<Activity>(activity);
         mMessagingHandler = messaging;
+        mUUID = UUID.randomUUID().toString();
     }
 
     private boolean checkService(String serviceID) {
@@ -89,6 +93,7 @@ public class MessagingSmsManager {
         intentSmsSent.putExtra(EXTRA_MSGTO, phone);
         String instanceIDString = Integer.toString(instanceID);
         intentSmsSent.putExtra(EXTRA_MSGINSTANCEID, instanceIDString);
+        intentSmsSent.putExtra(EXTRA_UUID, mUUID);
         int promiseIdInt = Integer.valueOf(asyncCallId);
         PendingIntent piSent = PendingIntent.getBroadcast(activity, 
                                                           promiseIdInt, 
@@ -98,6 +103,7 @@ public class MessagingSmsManager {
         intentSmsDelivered.putExtra(EXTRA_MSGID, asyncCallId);
         intentSmsDelivered.putExtra(EXTRA_MSGTEXT, smsMessage);
         intentSmsDelivered.putExtra(EXTRA_MSGINSTANCEID, instanceIDString);
+        intentSmsDelivered.putExtra(EXTRA_UUID, mUUID);
         PendingIntent piDelivered = PendingIntent.getBroadcast(activity, 
                                                                -promiseIdInt, 
                                                                intentSmsDelivered,
@@ -235,6 +241,8 @@ public class MessagingSmsManager {
             public void onReceive(Context content, Intent intent) {
                 Activity activity = mActivity.get();
                 if (activity == null) return;
+                String uuid = intent.getStringExtra(EXTRA_UUID);
+                if (null == uuid || !uuid.equals(mUUID)) return;
 
                 boolean error = getResultCode() != Activity.RESULT_OK;
                 String asyncCallId = intent.getStringExtra(EXTRA_MSGID);
@@ -283,6 +291,9 @@ public class MessagingSmsManager {
         mSmsDeliveredReceiver = new MessagingReceiver(mMessagingHandler) {
             @Override
             public void onReceive(Context content, Intent intent) {
+                String uuid = intent.getStringExtra(EXTRA_UUID);
+                if (null == uuid || !uuid.equals(mUUID)) return;
+
                 boolean error = getResultCode() != Activity.RESULT_OK;
                 String asyncCallId = intent.getStringExtra(EXTRA_MSGID);
                 int instanceID = Integer.valueOf(intent.getStringExtra(EXTRA_MSGINSTANCEID));
index 65cb893..11e0b31 100644 (file)
@@ -54,7 +54,7 @@ SmsManager.prototype.send = function(to, text, serviceID) {
       serviceID: serviceID
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 SmsManager.prototype.clear = function(serviceID) {
@@ -64,7 +64,7 @@ SmsManager.prototype.clear = function(serviceID) {
       serviceID: serviceID
     }
   }  
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 SmsManager.prototype.segmentInfo = function(text, serviceID) {
@@ -75,7 +75,7 @@ SmsManager.prototype.segmentInfo = function(text, serviceID) {
       serviceID: serviceID
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 var sms = new SmsManager();
@@ -292,7 +292,7 @@ exports.findMessages = function(filter, options) {
       options: options
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 exports.findConversations = function(groupBy, filter, options) {
@@ -307,7 +307,7 @@ exports.getMessage = function(type, messageID) {
       messageID: messageID
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 exports.deleteMessage = function(type, messageID) {
@@ -318,7 +318,7 @@ exports.deleteMessage = function(type, messageID) {
       messageID: messageID
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 exports.deleteConversation = function(type, conversationID) {
@@ -329,7 +329,7 @@ exports.deleteConversation = function(type, conversationID) {
       conversationID: conversationID
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 exports.markMessageRead = function(type, messageID, value) {
@@ -342,7 +342,7 @@ exports.markMessageRead = function(type, messageID, value) {
       value: value
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
 
 exports.markConversationRead = function(type, conversationID, value) {
@@ -355,5 +355,5 @@ exports.markConversationRead = function(type, conversationID, value) {
       value: value
     }
   }
-  return postMessage(_msg);
+  return createPromise(_msg);
 }
index c39674d..c9be134 100644 (file)
             </intent-filter>
         </activity>
         <activity
+            android:name="org.xwalk.core.sample.OnCreateWindowRequestedActivity"
+            android:label="Create Window"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="org.xwalk.core.sample.OnReceivedIconActivity"
+            android:label="Receive Icon"
+            android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+        <activity
             android:name="org.xwalk.core.sample.XWalkViewWithLayoutActivity"
             android:label="XWalkView UI Inflation"
             android:parentActivityName="org.xwalk.core.sample.XWalkEmbeddingAPISample" >
diff --git a/src/xwalk/runtime/android/sample/assets/create_window_1.html b/src/xwalk/runtime/android/sample/assets/create_window_1.html
new file mode 100644 (file)
index 0000000..6a82470
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Create Window 1</title>
+  <script type="text/javascript">
+    function createWindow() { window.open("create_window_2.html", "_blank", ""); }
+  </script>
+</head>
+<body>
+  <p>Create window by click <button id="new_window" onclick="createWindow();">button</button></p>
+</body>
+</html>
diff --git a/src/xwalk/runtime/android/sample/assets/create_window_2.html b/src/xwalk/runtime/android/sample/assets/create_window_2.html
new file mode 100644 (file)
index 0000000..2f65c0b
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Create Window 2</title>
+</head>
+<body>
+  <p>Create window by open <a id="new_window" href="new_window.html" target="_blank">link</a></p>
+</body>
+</html>
diff --git a/src/xwalk/runtime/android/sample/assets/favicon.html b/src/xwalk/runtime/android/sample/assets/favicon.html
new file mode 100644 (file)
index 0000000..6e60d4d
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Favicon</title>
+  <link rel="icon" href="icon.png" type="image/png" />
+</head>
+<body>
+  <p>The favicon will be shown by Toast</p>
+</body>
+</html>
diff --git a/src/xwalk/runtime/android/sample/assets/icon.png b/src/xwalk/runtime/android/sample/assets/icon.png
new file mode 100644 (file)
index 0000000..d94fd20
Binary files /dev/null and b/src/xwalk/runtime/android/sample/assets/icon.png differ
diff --git a/src/xwalk/runtime/android/sample/assets/new_window.html b/src/xwalk/runtime/android/sample/assets/new_window.html
new file mode 100644 (file)
index 0000000..3a52ae2
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>New Window</title>
+</head>
+<body>
+  <p>This is a new window</p>
+</body>
+</html>
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnCreateWindowRequestedActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnCreateWindowRequestedActivity.java
new file mode 100644 (file)
index 0000000..a7767ab
--- /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.
+
+package org.xwalk.core.sample;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.widget.LinearLayout;
+import android.webkit.ValueCallback;
+
+import java.util.LinkedList;
+
+import org.xwalk.core.XWalkNavigationHistory;
+import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
+
+public class OnCreateWindowRequestedActivity extends XWalkBaseActivity {
+    private LinearLayout mParent;
+    private LinkedList<XWalkView> mXWalkViewHistory = new LinkedList<XWalkView>();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mParent = new LinearLayout(OnCreateWindowRequestedActivity.this);
+        setContentView(mParent);
+
+        mXWalkView = new XWalkView(OnCreateWindowRequestedActivity.this, 
+                OnCreateWindowRequestedActivity.this);
+        setClient(mXWalkView);
+
+        mParent.addView(mXWalkView);
+        mXWalkViewHistory.add(mXWalkView);
+
+        mXWalkView.load("file:///android_asset/create_window_1.html", null);
+    }
+
+    private void setClient(XWalkView view) {
+        view.setUIClient(new XWalkUIClient(view) {
+            @Override
+            public boolean onCreateWindowRequested(XWalkView view, InitiateBy initiator,
+                    ValueCallback<XWalkView> callback) {
+                XWalkView newView = new XWalkView(OnCreateWindowRequestedActivity.this, 
+                        OnCreateWindowRequestedActivity.this);
+                setClient(newView);
+
+                mParent.removeView(mXWalkViewHistory.getLast());
+                mParent.addView(newView);
+                mXWalkViewHistory.add(newView);
+
+                callback.onReceiveValue(newView);
+                return true;
+            }
+        });
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
+            if (mXWalkViewHistory.getLast().getNavigationHistory().canGoBack()) {
+                mXWalkViewHistory.getLast().getNavigationHistory().navigate(
+                        XWalkNavigationHistory.Direction.BACKWARD, 1);
+                return true;
+            } else if (mXWalkViewHistory.size() > 1) {
+                mParent.removeView(mXWalkViewHistory.removeLast());
+                mParent.addView(mXWalkViewHistory.getLast());
+                return true;
+            }
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+}
diff --git a/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnReceivedIconActivity.java b/src/xwalk/runtime/android/sample/src/org/xwalk/core/sample/OnReceivedIconActivity.java
new file mode 100644 (file)
index 0000000..03b4e5a
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.sample;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.Message;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
+
+public class OnReceivedIconActivity extends XWalkBaseActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mXWalkView = new XWalkView(OnReceivedIconActivity.this, OnReceivedIconActivity.this);
+        setContentView(mXWalkView);
+
+        mXWalkView.setUIClient(new XWalkUIClient(mXWalkView) {
+            @Override
+            public void onIconAvailable(XWalkView view, String url, Message msg) {
+                msg.sendToTarget();
+            }
+
+            @Override
+            public void onReceivedIcon(XWalkView view, String url, Bitmap icon) {
+                Toast toast = Toast.makeText(OnReceivedIconActivity.this, "Favicon", 
+                        Toast.LENGTH_LONG);
+
+                ImageView favicon = new ImageView(OnReceivedIconActivity.this);
+                favicon.setImageBitmap(icon);
+
+                toast.setView(favicon);
+                toast.show();
+            }
+        });
+
+        mXWalkView.load("file:///android_asset/favicon.html", null);
+    }
+}
index 7877ade..dc1d74c 100644 (file)
@@ -169,4 +169,9 @@ void XWalkRenderViewHostExt::OnPageScaleFactorChanged(float page_scale_factor) {
     client_bridge->OnWebLayoutPageScaleFactorChanged(page_scale_factor);
 }
 
+void XWalkRenderViewHostExt::SetBackgroundColor(SkColor c) {
+  DCHECK(CalledOnValidThread());
+  Send(new XWalkViewMsg_SetBackgroundColor(web_contents()->GetRoutingID(), c));
+}
+
 }  // namespace xwalk
index 73be9a6..f27ad93 100644 (file)
@@ -62,6 +62,7 @@ class XWalkRenderViewHostExt : public content::WebContentsObserver,
   // the meta viewport tag.
   void SetInitialPageScale(double page_scale_factor);
   void SetJsOnlineProperty(bool network_up);
+  void SetBackgroundColor(SkColor c);
 
   // Sets the white list for Cross-Origin access.
   void SetOriginAccessWhitelist(const std::string& base_url,
index a7fb148..0054609 100644 (file)
@@ -413,7 +413,7 @@ static jlong Init(JNIEnv* env, jobject obj) {
 }
 
 bool RegisterXWalkContent(JNIEnv* env) {
-  return RegisterNativesImpl(env) >= 0;
+  return RegisterNativesImpl(env);
 }
 
 namespace {
@@ -501,4 +501,10 @@ void XWalkContent::HideGeolocationPrompt(const GURL& origin) {
   }
 }
 
+// Called by Java.
+void XWalkContent::SetBackgroundColor(JNIEnv* env, jobject obj, jint color) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  render_view_host_ext_->SetBackgroundColor(color);
+}
+
 }  // namespace xwalk
index 0a738d4..3e7ae73 100644 (file)
@@ -66,6 +66,7 @@ class XWalkContent {
                        jobject obj,
                        jstring path,
                        jstring manifest);
+  void SetBackgroundColor(JNIEnv* env, jobject obj, jint color);
 
   // Geolocation API support
   void ShowGeolocationPrompt(const GURL& origin,
index d5b30af..2f04730 100644 (file)
@@ -470,7 +470,7 @@ void XWalkContentsClientBridge::OnReceivedIcon(const GURL& icon_url,
 }
 
 bool RegisterXWalkContentsClientBridge(JNIEnv* env) {
-  return RegisterNativesImpl(env) >= 0;
+  return RegisterNativesImpl(env);
 }
 
 }  // namespace xwalk
index f979b2d..f5df627 100644 (file)
@@ -17,6 +17,7 @@
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "blink_upstream_version.h"  // NOLINT
 #include "content/public/browser/android/devtools_auth.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_http_handler.h"
@@ -28,7 +29,6 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
-#include "content/public/common/user_agent.h"
 #include "grit/xwalk_resources.h"
 #include "jni/XWalkDevToolsServer_jni.h"
 #include "net/socket/unix_domain_listen_socket_posix.h"
@@ -45,9 +45,6 @@ namespace {
 // Currently, the chrome version is hardcoded because of this dependancy.
 const char kFrontEndURL[] =
     "http://chrome-devtools-frontend.appspot.com/serve_rev/%s/devtools.html";
-const char kTargetTypePage[] = "page";
-const char kTargetTypeServiceWorker[] = "service_worker";
-const char kTargetTypeOther[] = "other";
 
 bool AuthorizeSocketAccessWithDebugPermission(
      const net::UnixDomainServerSocket::Credentials& credentials) {
@@ -58,79 +55,12 @@ bool AuthorizeSocketAccessWithDebugPermission(
       content::CanUserConnectToDevTools(credentials);
 }
 
-class Target : public content::DevToolsTarget {
- public:
-  explicit Target(scoped_refptr<content::DevToolsAgentHost> agent_host);
-
-  virtual std::string GetId() const OVERRIDE { return agent_host_->GetId(); }
-  virtual std::string GetType() const OVERRIDE {
-      switch (agent_host_->GetType()) {
-        case content::DevToolsAgentHost::TYPE_WEB_CONTENTS:
-           return kTargetTypePage;
-         case content::DevToolsAgentHost::TYPE_SERVICE_WORKER:
-           return kTargetTypeServiceWorker;
-         default:
-           break;
-       }
-       return kTargetTypeOther;
-     }
-  virtual std::string GetTitle() const OVERRIDE {
-    return agent_host_->GetTitle();
-  }
-
-  // TODO(hmin): Get the description about web contents view.
-  virtual std::string GetDescription() const OVERRIDE { return std::string(); }
-  virtual GURL GetURL() const OVERRIDE { return url_; }
-  virtual GURL GetFaviconURL() const OVERRIDE { return GURL(); }
-  virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
-    return last_activity_time_;
-  }
-  virtual std::string GetParentId() const OVERRIDE { return std::string(); }
-  virtual bool IsAttached() const OVERRIDE {
-    return agent_host_->IsAttached();
-  }
-  virtual scoped_refptr<DevToolsAgentHost> GetAgentHost() const OVERRIDE {
-    return agent_host_;
-  }
-
-  virtual bool Activate() const OVERRIDE {
-    WebContents* web_contents = agent_host_->GetWebContents();
-    if (!web_contents)
-      return false;
-    web_contents->GetDelegate()->ActivateContents(web_contents);
-    return true;
-  }
-
-  virtual bool Close() const OVERRIDE { return false; }
-
- private:
-  scoped_refptr<DevToolsAgentHost> agent_host_;
-  std::string id_;
-  std::string title_;
-  GURL url_;
-  GURL favicon_url_;
-  base::TimeTicks last_activity_time_;
-};
-
-Target::Target(scoped_refptr<content::DevToolsAgentHost> agent_host)
-    : agent_host_(agent_host) {
-  if (content::WebContents* web_contents = agent_host_->GetWebContents()) {
-    content::NavigationController& controller = web_contents->GetController();
-    content::NavigationEntry* entry = controller.GetActiveEntry();
-    if (entry != NULL && entry->GetURL().is_valid())
-      favicon_url_ = entry->GetFavicon().url;
-    last_activity_time_ = web_contents->GetLastActiveTime();
-  }
-}
-
 // Delegate implementation for the devtools http handler on android. A new
 // instance of this gets created each time devtools is enabled.
-class XWalkDevToolsHttpHandlerDelegate
+class XWalkAndroidDevToolsHttpHandlerDelegate
   : public content::DevToolsHttpHandlerDelegate {
  public:
-  explicit XWalkDevToolsHttpHandlerDelegate(
-    const net::UnixDomainServerSocket::AuthCallback& auth_callback)
-    : auth_callback_(auth_callback) {
+  XWalkAndroidDevToolsHttpHandlerDelegate() {
   }
 
   virtual std::string GetDiscoveryPageHTML() OVERRIDE {
@@ -152,49 +82,29 @@ class XWalkDevToolsHttpHandlerDelegate
     return scoped_ptr<net::StreamListenSocket>();
   }
  private:
-  const net::UnixDomainServerSocket::AuthCallback auth_callback_;
-  DISALLOW_COPY_AND_ASSIGN(XWalkDevToolsHttpHandlerDelegate);
-};
-
-class XWalkDevToolsDelegate
-  : public content::DevToolsManagerDelegate {
- public:
-  virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE {
-    return std::string();
-  }
-
-  virtual scoped_ptr<content::DevToolsTarget> CreateNewTarget(
-      const GURL&) OVERRIDE {
-    return scoped_ptr<content::DevToolsTarget>();
-  }
-  virtual void EnumerateTargets(TargetCallback callback) OVERRIDE {
-    TargetList targets;
-    content::DevToolsAgentHost::List agents =
-        content::DevToolsAgentHost::GetOrCreateAll();
-    for (content::DevToolsAgentHost::List::iterator it = agents.begin();
-         it != agents.end(); ++it) {
-      targets.push_back(new Target(*it));
-    }
-    callback.Run(targets);
-  }
+  DISALLOW_COPY_AND_ASSIGN(XWalkAndroidDevToolsHttpHandlerDelegate);
 };
 
 // Factory for UnixDomainServerSocket.
 class UnixDomainServerSocketFactory
     : public content::DevToolsHttpHandler::ServerSocketFactory {
  public:
-  explicit UnixDomainServerSocketFactory(const std::string& socket_name)
-      : content::DevToolsHttpHandler::ServerSocketFactory(socket_name, 0, 1) {}
+  explicit UnixDomainServerSocketFactory(
+      const std::string& socket_name,
+      const net::UnixDomainServerSocket::AuthCallback& auth_callback)
+      : content::DevToolsHttpHandler::ServerSocketFactory(socket_name, 0, 1),
+      auth_callback_(auth_callback) {}
 
  private:
   // content::DevToolsHttpHandler::ServerSocketFactory.
   virtual scoped_ptr<net::ServerSocket> Create() const OVERRIDE {
     return scoped_ptr<net::ServerSocket>(
         new net::UnixDomainServerSocket(
-            base::Bind(&content::CanUserConnectToDevTools),
+            auth_callback_,
             true /* use_abstract_namespace */));
   }
 
+  const net::UnixDomainServerSocket::AuthCallback auth_callback_;
   DISALLOW_COPY_AND_ASSIGN(UnixDomainServerSocketFactory);
 };
 
@@ -205,7 +115,8 @@ namespace xwalk {
 XWalkDevToolsServer::XWalkDevToolsServer(const std::string& socket_name)
     : socket_name_(socket_name),
       protocol_handler_(NULL),
-      allowed_uid_(0) {
+      allow_debug_permission_(false),
+      allow_socket_access_(false) {
 }
 
 XWalkDevToolsServer::~XWalkDevToolsServer() {
@@ -217,27 +128,30 @@ XWalkDevToolsServer::~XWalkDevToolsServer() {
 // process and connects to the devtools server.
 bool XWalkDevToolsServer::CanUserConnectToDevTools(
     const net::UnixDomainServerSocket::Credentials& credentials) {
-  if (credentials.user_id == allowed_uid_)
+  if (allow_socket_access_)
     return true;
+  if (allow_debug_permission_)
+    return AuthorizeSocketAccessWithDebugPermission(credentials);
   return content::CanUserConnectToDevTools(credentials);
 }
 
-void XWalkDevToolsServer::Start(bool allow_debug_permission) {
+void XWalkDevToolsServer::Start(bool allow_debug_permission,
+                                bool allow_socket_access) {
+  allow_debug_permission_ = allow_debug_permission;
+  allow_socket_access_ = allow_socket_access;
   if (protocol_handler_)
     return;
 
   net::UnixDomainServerSocket::AuthCallback auth_callback =
-      allow_debug_permission ?
-          base::Bind(&AuthorizeSocketAccessWithDebugPermission) :
-          base::Bind(&XWalkDevToolsServer::CanUserConnectToDevTools,
-              base::Unretained(this));
+      base::Bind(&XWalkDevToolsServer::CanUserConnectToDevTools,
+                 base::Unretained(this));
 
   scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory> factory(
-      new UnixDomainServerSocketFactory(socket_name_));
+      new UnixDomainServerSocketFactory(socket_name_, auth_callback));
   protocol_handler_ = content::DevToolsHttpHandler::Start(
       factory.Pass(),
-      base::StringPrintf(kFrontEndURL, content::GetWebKitRevision().c_str()),
-      new XWalkDevToolsHttpHandlerDelegate(auth_callback), base::FilePath());
+      base::StringPrintf(kFrontEndURL, BLINK_UPSTREAM_REVISION),
+      new XWalkAndroidDevToolsHttpHandlerDelegate(), base::FilePath());
 }
 
 void XWalkDevToolsServer::Stop() {
@@ -247,16 +161,14 @@ void XWalkDevToolsServer::Stop() {
   // deletion.
   protocol_handler_->Stop();
   protocol_handler_ = NULL;
+  allow_socket_access_ = false;
+  allow_debug_permission_ = false;
 }
 
 bool XWalkDevToolsServer::IsStarted() const {
   return protocol_handler_;
 }
 
-void XWalkDevToolsServer::AllowConnectionFromUid(uid_t uid) {
-  allowed_uid_ = uid;
-}
-
 bool RegisterXWalkDevToolsServer(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
@@ -283,23 +195,16 @@ static void SetRemoteDebuggingEnabled(JNIEnv* env,
                                       jobject obj,
                                       jlong server,
                                       jboolean enabled,
-                                      jboolean allow_debug_permission) {
+                                      jboolean allow_debug_permission,
+                                      jboolean allow_socket_access) {
   XWalkDevToolsServer* devtools_server =
       reinterpret_cast<XWalkDevToolsServer*>(server);
-  if (enabled) {
-    devtools_server->Start(allow_debug_permission);
+  if (enabled == JNI_TRUE) {
+    devtools_server->Start(allow_debug_permission == JNI_TRUE,
+                           allow_socket_access == JNI_TRUE);
   } else {
     devtools_server->Stop();
   }
 }
 
-static void AllowConnectionFromUid(JNIEnv* env,
-                                    jobject obj,
-                                    jlong server,
-                                    jint uid) {
-  XWalkDevToolsServer* devtools_server =
-      reinterpret_cast<XWalkDevToolsServer*>(server);
-  devtools_server->AllowConnectionFromUid((uid_t) uid);
-}
-
 }  // namespace xwalk
index 7f140f2..4ee689b 100644 (file)
@@ -23,7 +23,7 @@ class XWalkDevToolsServer {
   ~XWalkDevToolsServer();
 
   // Opens linux abstract socket to be ready for remote debugging.
-  void Start(bool allow_debug_permission);
+  void Start(bool allow_debug_permission, bool allow_socket_access);
 
   // Closes debugging socket, stops debugging.
   void Stop();
@@ -38,7 +38,8 @@ class XWalkDevToolsServer {
 
   std::string socket_name_;
   content::DevToolsHttpHandler* protocol_handler_;
-  uid_t allowed_uid_;
+  bool allow_debug_permission_;
+  bool allow_socket_access_;
 
   DISALLOW_COPY_AND_ASSIGN(XWalkDevToolsServer);
 };
index 27d279f..7cc1450 100644 (file)
@@ -77,7 +77,7 @@ XWalkHttpAuthHandlerBase* XWalkHttpAuthHandlerBase::Create(
 }
 
 bool RegisterXWalkHttpAuthHandler(JNIEnv* env) {
-  return RegisterNativesImpl(env) >= 0;
+  return RegisterNativesImpl(env);
 }
 
 }  // namespace xwalk
index e7566d1..7900199 100644 (file)
@@ -38,7 +38,7 @@ static void SetDirectory(JNIEnv* env, jclass clazz,
 }
 
 bool RegisterXWalkPathHelper(JNIEnv* env) {
-  return RegisterNativesImpl(env) >= 0;
+  return RegisterNativesImpl(env);
 }
 
 }  // namespace xwalk
index 528f049..ba26c31 100644 (file)
@@ -237,7 +237,7 @@ static jstring GetDefaultUserAgent(JNIEnv* env, jclass clazz) {
 }
 
 bool RegisterXWalkSettings(JNIEnv* env) {
-  return RegisterNativesImpl(env) >= 0;
+  return RegisterNativesImpl(env);
 }
 
 }  // namespace xwalk
index 1b992f1..f6e3e52 100644 (file)
@@ -19,7 +19,7 @@ jboolean IsLibraryBuiltForIA(JNIEnv* env, jclass jcaller) {
 }
 
 bool RegisterXWalkViewDelegate(JNIEnv* env) {
-  return RegisterNativesImpl(env) >= 0;
+  return RegisterNativesImpl(env);
 }
 
 }  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/blink_upstream_version.h.in b/src/xwalk/runtime/browser/blink_upstream_version.h.in
new file mode 100644 (file)
index 0000000..ab6d1ed
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2014 Intel Corp. All rights reserved.
+// Use of this source is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// upstream_blink_version.h is generated from upstream_blink_version.h.in.  Edit the source!
+
+#define BLINK_UPSTREAM_REVISION "@@UPSTREAM_REVISION@"
index 229ff6f..c9a11e4 100644 (file)
 #include "testing/gmock/include/gmock/gmock.h"
 
 using xwalk::Runtime;
+namespace {
+Runtime* CreateWithDefaultWindow(
+    xwalk::RuntimeContext* runtime_context, const GURL& url,
+    Runtime::Observer* observer = NULL) {
+  Runtime* runtime = Runtime::Create(runtime_context, observer);
+  runtime->LoadURL(url);
+#if !defined(OS_ANDROID)
+  xwalk::RuntimeUIStrategy ui_strategy;
+  xwalk::NativeAppWindow::CreateParams params;
+  ui_strategy.Show(runtime, params);
+#endif
+  return runtime;
+}
+}  // namespace
 
 class XWalkDevToolsTest : public InProcessBrowserTest {
  public:
@@ -30,7 +44,7 @@ class XWalkDevToolsTest : public InProcessBrowserTest {
 
 IN_PROC_BROWSER_TEST_F(XWalkDevToolsTest, RemoteDebugging) {
   GURL localhost_url("http://127.0.0.1:9222");
-  Runtime* debugging_host = Runtime::CreateWithDefaultWindow(
+  Runtime* debugging_host = CreateWithDefaultWindow(
       GetRuntimeContext(), localhost_url, runtime_registry());
   content::WaitForLoadStop(debugging_host->web_contents());
   base::string16 real_title = debugging_host->web_contents()->GetTitle();
index 2f8d3a5..6a8d5f8 100644 (file)
@@ -6,22 +6,28 @@
 
 #include <string>
 
+#include "base/base64.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_http_handler.h"
 #include "content/public/browser/devtools_target.h"
 #include "content/public/browser/favicon_status.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 #include "grit/xwalk_resources.h"
 #include "net/socket/tcp_listen_socket.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/snapshot/snapshot.h"
 #include "xwalk/runtime/browser/runtime.h"
 
 using content::DevToolsAgentHost;
 using content::RenderViewHost;
+using content::RenderWidgetHostView;
 using content::WebContents;
 
 namespace {
@@ -50,7 +56,7 @@ class Target : public content::DevToolsTarget {
     return agent_host_->GetTitle();
   }
   virtual std::string GetDescription() const OVERRIDE { return std::string(); }
-  virtual GURL GetURL() const OVERRIDE { return url_; }
+  virtual GURL GetURL() const OVERRIDE { return  agent_host_->GetURL(); }
   virtual GURL GetFaviconURL() const OVERRIDE { return favicon_url_; }
   virtual base::TimeTicks GetLastActivityTime() const OVERRIDE {
     return last_activity_time_;
@@ -66,10 +72,11 @@ class Target : public content::DevToolsTarget {
   virtual bool Close() const OVERRIDE;
 
  private:
+  GURL GetFaviconDataURL(WebContents* web_contents) const;
+
   scoped_refptr<DevToolsAgentHost> agent_host_;
   std::string id_;
   std::string title_;
-  GURL url_;
   GURL favicon_url_;
   base::TimeTicks last_activity_time_;
 };
@@ -81,30 +88,55 @@ Target::Target(scoped_refptr<content::DevToolsAgentHost> agent_host)
     content::NavigationEntry* entry = controller.GetActiveEntry();
     if (entry != NULL && entry->GetURL().is_valid())
       favicon_url_ = entry->GetFavicon().url;
+    if (favicon_url_.is_empty())
+      favicon_url_ = GetFaviconDataURL(web_contents);
     last_activity_time_ = web_contents->GetLastActiveTime();
   }
 }
 
+GURL Target::GetFaviconDataURL(WebContents* web_contents) const {
+  // Convert icon image to "data:" url.
+  xwalk::Runtime* runtime =
+      static_cast<xwalk::Runtime*>(web_contents->GetDelegate());
+  if (!runtime || runtime->app_icon().IsEmpty())
+    return GURL();
+  scoped_refptr<base::RefCountedMemory> icon_bytes =
+      runtime->app_icon().Copy1xPNGBytes();
+  std::string str_url;
+  str_url.append(reinterpret_cast<const char*>(icon_bytes->front()),
+                 icon_bytes->size());
+  base::Base64Encode(str_url, &str_url);
+  str_url.insert(0, "data:image/png;base64,");
+  return GURL(str_url);
+}
+
 bool Target::Activate() const {
-  WebContents* web_contents = agent_host_->GetWebContents();
-  if (!web_contents)
-    return false;
-  web_contents->GetDelegate()->ActivateContents(web_contents);
-  return true;
+  return agent_host_->Activate();
 }
 
 bool Target::Close() const {
-  RenderViewHost* rvh = agent_host_->GetWebContents()->GetRenderViewHost();
-  if (!rvh)
-    return false;
-  rvh->ClosePage();
-  return true;
+  return agent_host_->Close();
 }
 
 }  // namespace
 
 namespace xwalk {
 
+namespace {
+Runtime* CreateWithDefaultWindow(
+    RuntimeContext* runtime_context, const GURL& url,
+    Runtime::Observer* observer = NULL) {
+  Runtime* runtime = Runtime::Create(runtime_context, observer);
+  runtime->LoadURL(url);
+#if !defined(OS_ANDROID)
+  RuntimeUIStrategy ui_strategy;
+  NativeAppWindow::CreateParams params;
+  ui_strategy.Show(runtime, params);
+#endif
+  return runtime;
+}
+}  // namespace
+
 XWalkDevToolsHttpHandlerDelegate::XWalkDevToolsHttpHandlerDelegate() {
 }
 
@@ -116,6 +148,15 @@ std::string XWalkDevToolsHttpHandlerDelegate::GetDiscoveryPageHTML() {
       IDR_DEVTOOLS_FRONTEND_PAGE_HTML).as_string();
 }
 
+void XWalkDevToolsDelegate::ProcessAndSaveThumbnail(
+    const GURL& url,
+    scoped_refptr<base::RefCountedBytes> png) {
+  const std::vector<unsigned char>& png_data = png->data();
+  std::string png_string_data(reinterpret_cast<const char*>(&png_data[0]),
+                              png_data.size());
+  thumbnail_map_[url] = png_string_data;
+}
+
 bool XWalkDevToolsHttpHandlerDelegate::BundlesFrontendResources() {
   return true;
 }
@@ -132,7 +173,8 @@ XWalkDevToolsHttpHandlerDelegate::CreateSocketForTethering(
 }
 
 XWalkDevToolsDelegate::XWalkDevToolsDelegate(RuntimeContext* runtime_context)
-    : runtime_context_(runtime_context) {
+    : runtime_context_(runtime_context),
+      weak_factory_(this) {
 }
 
 XWalkDevToolsDelegate::~XWalkDevToolsDelegate() {
@@ -145,12 +187,34 @@ base::DictionaryValue* XWalkDevToolsDelegate::HandleCommand(
 }
 
 std::string XWalkDevToolsDelegate::GetPageThumbnailData(const GURL& url) {
+  if (thumbnail_map_.find(url) != thumbnail_map_.end())
+    return thumbnail_map_[url];
+  // TODO(YangangHan): Support real time thumbnail.
+  content::DevToolsAgentHost::List agents =
+      content::DevToolsAgentHost::GetOrCreateAll();
+  for (auto& it : agents) {
+    WebContents* web_contents = it.get()->GetWebContents();
+    if (web_contents && web_contents->GetURL() == url) {
+      RenderWidgetHostView* render_widget_host_view =
+          web_contents->GetRenderViewHost()->GetView();
+      gfx::Rect snapshot_bounds(
+        render_widget_host_view->GetViewBounds().size());
+      ui::GrabViewSnapshotAsync(
+        render_widget_host_view->GetNativeView(),
+        snapshot_bounds,
+        base::ThreadTaskRunnerHandle::Get(),
+        base::Bind(&XWalkDevToolsDelegate::ProcessAndSaveThumbnail,
+                   weak_factory_.GetWeakPtr(),
+                   url));
+        break;
+    }
+  }
   return std::string();
 }
 
 scoped_ptr<content::DevToolsTarget>
 XWalkDevToolsDelegate::CreateNewTarget(const GURL& url) {
-  Runtime* runtime = Runtime::CreateWithDefaultWindow(
+  Runtime* runtime = CreateWithDefaultWindow(
       runtime_context_, GURL(url::kAboutBlankURL));
   return scoped_ptr<content::DevToolsTarget>(
       new Target(DevToolsAgentHost::GetOrCreateFor(runtime->web_contents())));
@@ -158,13 +222,15 @@ XWalkDevToolsDelegate::CreateNewTarget(const GURL& url) {
 
 void XWalkDevToolsDelegate::EnumerateTargets(TargetCallback callback) {
   TargetList targets;
-    content::DevToolsAgentHost::List agents =
-        content::DevToolsAgentHost::GetOrCreateAll();
-    for (content::DevToolsAgentHost::List::iterator it = agents.begin();
-         it != agents.end(); ++it) {
+  content::DevToolsAgentHost::List agents =
+      content::DevToolsAgentHost::GetOrCreateAll();
+  for (content::DevToolsAgentHost::List::iterator it = agents.begin();
+       it != agents.end(); ++it) {
+#if !defined(OS_ANDROID)
     Runtime* runtime =
         static_cast<Runtime*>((*it)->GetWebContents()->GetDelegate());
     if (runtime && runtime->remote_debugging_enabled())
+#endif
       targets.push_back(new Target(*it));
   }
   callback.Run(targets);
index 66307e8..2a35fd6 100644 (file)
@@ -5,11 +5,14 @@
 #ifndef XWALK_RUNTIME_BROWSER_DEVTOOLS_XWALK_DEVTOOLS_DELEGATE_H_
 #define XWALK_RUNTIME_BROWSER_DEVTOOLS_XWALK_DEVTOOLS_DELEGATE_H_
 
+#include <map>
 #include <string>
 #include <vector>
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/memory/weak_ptr.h"
 #include "content/public/browser/devtools_http_handler_delegate.h"
 #include "content/public/browser/devtools_manager_delegate.h"
 #include "url/gurl.h"
@@ -58,9 +61,14 @@ class XWalkDevToolsDelegate : public content::DevToolsManagerDelegate {
       const GURL& url) OVERRIDE;
   virtual void EnumerateTargets(TargetCallback callback) OVERRIDE;
   virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE;
+  void ProcessAndSaveThumbnail(const GURL& url,
+                               scoped_refptr<base::RefCountedBytes> png);
 
  private:
+  using ThumbnailMap = std::map<GURL, std::string>;
+  ThumbnailMap thumbnail_map_;
   RuntimeContext* runtime_context_;
+  base::WeakPtrFactory<XWalkDevToolsDelegate> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(XWalkDevToolsDelegate);
 };
 
index 7426247..5f86702 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
 #include "xwalk/runtime/browser/image_util.h"
 #include "xwalk/runtime/browser/media/media_capture_devices_dispatcher.h"
 #include "xwalk/runtime/browser/runtime_context.h"
@@ -22,6 +23,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/native_widget_types.h"
 
+#if defined(OS_TIZEN)
+#include "content/public/browser/site_instance.h"
+#include "xwalk/application/browser/application.h"
+#include "xwalk/application/browser/application_system.h"
+#include "xwalk/application/browser/application_service.h"
+#endif
+
+#if !defined(OS_ANDROID)
+#include "xwalk/runtime/browser/runtime_ui_strategy.h"
+#endif
+
 using content::FaviconURL;
 using content::WebContents;
 
 namespace xwalk {
 
-namespace {
-
-// The default size for web content area size.
-const int kDefaultWidth = 840;
-const int kDefaultHeight = 600;
-
-}  // namespace
-
-// static
-Runtime* Runtime::CreateWithDefaultWindow(
-    RuntimeContext* runtime_context, const GURL& url, Observer* observer) {
-  Runtime* runtime = Runtime::Create(runtime_context, observer);
-  runtime->LoadURL(url);
-  runtime->AttachDefaultWindow();
-  return runtime;
-}
-
 // static
 Runtime* Runtime::Create(RuntimeContext* runtime_context,
                          Observer* observer,
@@ -60,12 +56,7 @@ Runtime* Runtime::Create(RuntimeContext* runtime_context,
   params.routing_id = MSG_ROUTING_NONE;
   WebContents* web_contents = WebContents::Create(params);
 
-  Runtime* runtime = new Runtime(web_contents, observer);
-#if defined(OS_TIZEN_MOBILE)
-  runtime->InitRootWindow();
-#endif
-
-  return runtime;
+  return new Runtime(web_contents, observer);
 }
 
 Runtime::Runtime(content::WebContents* web_contents, Observer* observer)
@@ -81,9 +72,6 @@ Runtime::Runtime(content::WebContents* web_contents, Observer* observer)
        xwalk::NOTIFICATION_RUNTIME_OPENED,
        content::Source<Runtime>(this),
        content::NotificationService::NoDetails());
-#if defined(OS_TIZEN_MOBILE)
-  root_window_ = NULL;
-#endif
   if (observer_)
     observer_->OnRuntimeAdded(this);
 }
@@ -97,44 +85,16 @@ Runtime::~Runtime() {
     observer_->OnRuntimeRemoved(this);
 }
 
-void Runtime::AttachDefaultWindow() {
-  NativeAppWindow::CreateParams params;
-  AttachWindow(params);
-}
-
-void Runtime::AttachWindow(const NativeAppWindow::CreateParams& params) {
-#if defined(OS_ANDROID)
-  NOTIMPLEMENTED();
-#else
-  CHECK(!window_);
-  NativeAppWindow::CreateParams effective_params(params);
-  ApplyWindowDefaultParams(&effective_params);
-
-  // Set the app icon if it is passed from command line.
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kAppIcon)) {
-    base::FilePath icon_file =
-        command_line->GetSwitchValuePath(switches::kAppIcon);
-    app_icon_ = xwalk_utils::LoadImageFromFilePath(icon_file);
-  } else {
-    // Otherwise, use the default icon for Crosswalk app.
-    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-    app_icon_ = rb.GetNativeImageNamed(IDR_XWALK_ICON_48);
-  }
-
+void Runtime::EnableTitleUpdatedNotification() {
   registrar_.Add(this,
-        content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
-        content::Source<content::WebContents>(web_contents_.get()));
+                 content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
+                 content::Source<content::WebContents>(web_contents_.get()));
+}
 
-  window_ = NativeAppWindow::Create(effective_params);
-  if (!app_icon_.IsEmpty())
+void Runtime::set_app_icon(const gfx::Image& app_icon) {
+  app_icon_ = app_icon;
+  if (window_ && !app_icon_.IsEmpty())
     window_->UpdateIcon(app_icon_);
-  window_->Show();
-#if defined(OS_TIZEN_MOBILE)
-  if (root_window_)
-    root_window_->Show();
-#endif
-#endif
 }
 
 void Runtime::LoadURL(const GURL& url) {
@@ -165,10 +125,24 @@ content::RenderProcessHost* Runtime::GetRenderProcessHost() {
 //////////////////////////////////////////////////////
 content::WebContents* Runtime::OpenURLFromTab(
     content::WebContents* source, const content::OpenURLParams& params) {
-  // The only one disposition we would take into consideration.
+#if defined(OS_ANDROID)
   DCHECK(params.disposition == CURRENT_TAB);
   source->GetController().LoadURL(
       params.url, params.referrer, params.transition, std::string());
+#else
+  if (params.disposition == CURRENT_TAB) {
+    source->GetController().LoadURL(
+        params.url, params.referrer, params.transition, std::string());
+  } else if (params.disposition == NEW_WINDOW ||
+             params.disposition == NEW_POPUP ||
+             params.disposition == NEW_FOREGROUND_TAB ||
+             params.disposition == NEW_BACKGROUND_TAB) {
+    // TODO(xinchao): Excecuting JaveScript code is a temporary solution,
+    // need to be implemented by creating a new runtime window instead.
+    web_contents()->GetFocusedFrame()->ExecuteJavaScript(
+        base::UTF8ToUTF16("window.open('" + params.url.spec() + "')"));
+  }
+#endif
   return source;
 }
 
@@ -232,11 +206,7 @@ void Runtime::WebContentsCreated(
     const base::string16& frame_name,
     const GURL& target_url,
     content::WebContents* new_contents) {
-  Runtime* new_runtime = new Runtime(new_contents, observer_);
-#if defined(OS_TIZEN_MOBILE)
-  new_runtime->SetRootWindow(root_window_);
-#endif
-  new_runtime->AttachDefaultWindow();
+  new Runtime(new_contents, observer_);
 }
 
 void Runtime::DidNavigateMainFramePostCommit(
@@ -344,57 +314,4 @@ void Runtime::RequestMediaAccessPermission(
   XWalkMediaCaptureDevicesDispatcher::RunRequestMediaAccessPermission(
       web_contents, request, callback);
 }
-
-void Runtime::ApplyWindowDefaultParams(NativeAppWindow::CreateParams* params) {
-  if (!params->delegate)
-    params->delegate = this;
-  if (!params->web_contents)
-    params->web_contents = web_contents_.get();
-  if (params->bounds.IsEmpty())
-    params->bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
-#if defined(OS_TIZEN_MOBILE)
-  if (root_window_)
-    params->parent = root_window_->GetNativeWindow();
-#endif
-  ApplyFullScreenParam(params);
-}
-
-void Runtime::ApplyFullScreenParam(NativeAppWindow::CreateParams* params) {
-  DCHECK(params);
-  if (params->state == ui::SHOW_STATE_FULLSCREEN)
-    fullscreen_options_ |= FULLSCREEN_FOR_LAUNCH;
-  else
-    fullscreen_options_ &= ~FULLSCREEN_FOR_LAUNCH;
-}
-
-#if defined(OS_TIZEN_MOBILE)
-void Runtime::CloseRootWindow() {
-  if (root_window_) {
-    root_window_->Close();
-    root_window_ = NULL;
-  }
-}
-
-void Runtime::ApplyRootWindowParams(NativeAppWindow::CreateParams* params) {
-  if (!params->delegate)
-    params->delegate = this;
-  if (params->bounds.IsEmpty())
-    params->bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
-  ApplyFullScreenParam(params);
-}
-
-void Runtime::InitRootWindow() {
-  if (root_window_)
-    return;
-
-  NativeAppWindow::CreateParams params;
-  ApplyRootWindowParams(&params);
-  root_window_ = NativeAppWindow::Create(params);
-}
-
-void Runtime::SetRootWindow(NativeAppWindow* window) {
-  root_window_= window;
-}
-
-#endif
 }  // namespace xwalk
index 5b48ab5..f12dfdb 100644 (file)
@@ -10,6 +10,7 @@
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "xwalk/runtime/browser/runtime_ui_strategy.h"
 #include "xwalk/runtime/browser/ui/native_app_window.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -55,26 +56,34 @@ class Runtime : public content::WebContentsDelegate,
       virtual ~Observer() {}
   };
 
+  // Fullscreen options.
+  enum FullscreenOptions {
+    NO_FULLSCREEN = 0,
+    // Fullscreen entered by launch with "--fullscreen".
+    FULLSCREEN_FOR_LAUNCH = 1,
+    // Fullscreen entered by HTML requestFullscreen.
+    FULLSCREEN_FOR_TAB = 1 << 1,
+  };
+
   void SetObserver(Observer* observer) { observer_ = observer; }
 
-  // Create a new Runtime instance which binds to a default app window.
-  static Runtime* CreateWithDefaultWindow(RuntimeContext*,
-                                          const GURL&, Observer* = NULL);
   // Create a new Runtime instance with the given browsing context.
   static Runtime* Create(RuntimeContext*,
                          Observer* = NULL, content::SiteInstance* = NULL);
 
-  // Attach to a default app window.
-  void AttachDefaultWindow();
-  // Attach to a app window created with 'params'.
-  void AttachWindow(const NativeAppWindow::CreateParams& params);
-
   void LoadURL(const GURL& url);
   void Close();
 
   content::WebContents* web_contents() const { return web_contents_.get(); }
   NativeAppWindow* window() const { return window_; }
+  void set_window(NativeAppWindow* window) { window_ = window; }
   gfx::Image app_icon() const { return app_icon_; }
+  void set_app_icon(const gfx::Image& app_icon);
+  void EnableTitleUpdatedNotification();
+  unsigned int fullscreen_options() { return fullscreen_options_; }
+  void set_fullscreen_options(unsigned int options) {
+    fullscreen_options_ = options;
+  }
 
   content::RenderProcessHost* GetRenderProcessHost();
 
@@ -83,10 +92,6 @@ class Runtime : public content::WebContentsDelegate,
   }
   bool remote_debugging_enabled() const { return remote_debugging_enabled_; }
 
-#if defined(OS_TIZEN_MOBILE)
-  void CloseRootWindow();
-#endif
-
  protected:
   Runtime(content::WebContents* web_contents, Observer* observer);
   virtual ~Runtime();
@@ -158,15 +163,6 @@ class Runtime : public content::WebContentsDelegate,
   // NativeAppWindowDelegate implementation.
   virtual void OnWindowDestroyed() OVERRIDE;
 
-  void ApplyWindowDefaultParams(NativeAppWindow::CreateParams* params);
-  void ApplyFullScreenParam(NativeAppWindow::CreateParams* params);
-
-#if defined(OS_TIZEN_MOBILE)
-  void ApplyRootWindowParams(NativeAppWindow::CreateParams* params);
-  void SetRootWindow(NativeAppWindow* window);
-  void InitRootWindow();
-#endif
-
   // Notification manager.
   content::NotificationRegistrar registrar_;
 
@@ -175,23 +171,10 @@ class Runtime : public content::WebContentsDelegate,
 
   NativeAppWindow* window_;
 
-#if defined(OS_TIZEN_MOBILE)
-  NativeAppWindow* root_window_;
-#endif
-
   gfx::Image app_icon_;
 
   base::WeakPtrFactory<Runtime> weak_ptr_factory_;
 
-  // Fullscreen options.
-  enum FullscreenOptions {
-    NO_FULLSCREEN = 0,
-    // Fullscreen entered by launch with "--fullscreen".
-    FULLSCREEN_FOR_LAUNCH = 1,
-    // Fullscreen entered by HTML requestFullscreen.
-    FULLSCREEN_FOR_TAB = 1 << 1,
-  };
-
   unsigned int fullscreen_options_;
   bool remote_debugging_enabled_;
 
index 10f8bda..b422a13 100644 (file)
@@ -258,6 +258,12 @@ net::URLRequestContextGetter*
 
   context_getters_.insert(
       std::make_pair(partition_path.value(), context_getter));
+  // Make sure that the default url request getter has been initialized,
+  // please refer to https://crosswalk-project.org/jira/browse/XWALK-2890
+  // for more details.
+  if (!url_request_getter_.get())
+    CreateRequestContext(protocol_handlers, request_interceptors.Pass());
+
   return context_getter.get();
 #endif
 }
diff --git a/src/xwalk/runtime/browser/runtime_defered_ui_strategy.cc b/src/xwalk/runtime/browser/runtime_defered_ui_strategy.cc
new file mode 100644 (file)
index 0000000..2cad3be
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/browser/runtime_defered_ui_strategy.h"
+
+#include "xwalk/runtime/browser/runtime.h"
+
+namespace xwalk {
+RuntimeDeferedUIStrategy::RuntimeDeferedUIStrategy()
+    : defered_show_(true) {}
+
+RuntimeDeferedUIStrategy::~RuntimeDeferedUIStrategy() {}
+
+void RuntimeDeferedUIStrategy::Show(
+    Runtime* runtime, const NativeAppWindow::CreateParams& params) {
+  if (!defered_show_) {
+    RuntimeUIStrategy::Show(runtime, params);
+    return;
+  }
+
+  runtime_map_[runtime] = params;
+}
+
+void RuntimeDeferedUIStrategy::ShowStoredRuntimes() {
+  for (const auto& item : runtime_map_) {
+    RuntimeUIStrategy::Show(item.first, item.second);
+  }
+  defered_show_ = false;
+}
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/runtime_defered_ui_strategy.h b/src/xwalk/runtime/browser/runtime_defered_ui_strategy.h
new file mode 100644 (file)
index 0000000..4ccd189
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_BROWSER_RUNTIME_DEFERED_UI_STRATEGY_H_
+#define XWALK_RUNTIME_BROWSER_RUNTIME_DEFERED_UI_STRATEGY_H_
+
+#include <map>
+
+#include "xwalk/runtime/browser/runtime_ui_strategy.h"
+#include "xwalk/runtime/browser/ui/native_app_window.h"
+
+namespace xwalk {
+class Runtime;
+
+class RuntimeDeferedUIStrategy : public RuntimeUIStrategy {
+ public:
+  RuntimeDeferedUIStrategy();
+  virtual ~RuntimeDeferedUIStrategy();
+
+  // Override from RuntimeUIStrategy.
+  virtual void Show(Runtime* runtime,
+                    const NativeAppWindow::CreateParams& params) OVERRIDE;
+
+  void ShowStoredRuntimes();
+
+ private:
+  std::map<Runtime*, NativeAppWindow::CreateParams> runtime_map_;
+  bool defered_show_;
+};
+
+inline RuntimeDeferedUIStrategy*
+ToRuntimeDeferedUIStrategy(RuntimeUIStrategy* ui_strategy) {
+  return static_cast<RuntimeDeferedUIStrategy*>(ui_strategy);
+}
+}  // namespace xwalk
+#endif  // XWALK_RUNTIME_BROWSER_RUNTIME_DEFERED_UI_STRATEGY_H_
index 02cf298..39092de 100644 (file)
@@ -30,4 +30,8 @@ bool IsVisible(gfx::NativeView view) {
   return true;
 }
 
+void OpenExternal(const GURL& url) {
+  NOTIMPLEMENTED();
+}
+
 }  // namespace platform_util
index 1e58c42..1b25c7c 100644 (file)
@@ -4,10 +4,14 @@
 
 #include "xwalk/runtime/browser/runtime_platform_util.h"
 
+#include "base/bind.h"
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/process/kill.h"
 #include "base/process/launch.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_proxy.h"
 #include "url/gurl.h"
 
 namespace platform_util {
@@ -16,8 +20,91 @@ namespace {
 // In some Tizen releases, there exists a system browser called 'MiniBrowser',
 // which we can use to open an external link from a web app.
 const char kWebBrowserPath[] = "/usr/bin/MiniBrowser";
+
+typedef base::Callback<void (const GURL&, dbus::MessageWriter*)> ParamsWriter;
+
+struct ProtocolDBusServiceInfo {
+  const char* scheme;
+  const char* service;
+  const char* interface;
+  const char* method;
+  const char* object_path;
+  ParamsWriter params_writer;
+};
+
+void ParseAndWriteTelParams(const GURL& url,
+                            dbus::MessageWriter* dbus_writer) {
+  // Phone number
+  dbus_writer->AppendString(url.GetContent());
+  // Always don't auto dial
+  dbus_writer->AppendBool(false);
+}
+
+void ParseAndWriteMailParams(const GURL& uri,
+                             dbus::MessageWriter* dbus_writer) {
+}
+
+void ParseAndWriteSmsParams(const GURL& url,
+                            dbus::MessageWriter* dbus_writer) {
+  // Support the case sms:12345678?body=Hello
+  std::string query = url.query();
+  std::string content = url.GetContent();
+  // Extract the phone number
+  const std::string number = content.substr(0, content.find(query) - 1);
+  // Remove "body="
+  const std::string body = query.erase(0, 5);
+
+  dbus_writer->AppendString(number);
+  dbus_writer->AppendString(body);
+  // Always don't auto dial
+  dbus_writer->AppendBool(false);
+}
+
+const ProtocolDBusServiceInfo protocol_dbus_services[] = {
+  {"tel", "org.tizen.dialer", "org.tizen.dialer.Control", "Dial", "/",
+      base::Bind(ParseAndWriteTelParams)},
+  {"mailto", "org.tizen.email_service", "org.tizen.email_service", "Launch",
+      "/org/tizen/email_service",
+      base::Bind(ParseAndWriteMailParams)},
+  {"sms", "org.tizen.dialer", "org.tizen.dialer.Control", "Send", "/",
+      base::Bind(ParseAndWriteSmsParams)},
+};
+
+bool CallDbusService(const ProtocolDBusServiceInfo& info,
+                     const GURL& url) {
+  const dbus::ObjectPath dbus_path(info.object_path);
+
+  dbus::Bus::Options options;
+  scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
+  dbus::ObjectProxy* app_proxy =
+      bus->GetObjectProxy(info.service, dbus_path);
+  if (!app_proxy) {
+    VLOG(1) << "app_proxy failed.";
+    return false;
+  }
+
+  dbus::MethodCall method_call(info.interface, info.method);
+  dbus::MessageWriter writer(&method_call);
+  info.params_writer.Run(url, &writer);
+
+  app_proxy->CallMethod(&method_call,
+                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                        dbus::ObjectProxy::EmptyResponseCallback());
+
+  return true;
+}
 }  // namespace
 
+bool HandleExternalProtocol(const GURL& url) {
+  for (size_t i = 0; i < arraysize(protocol_dbus_services); ++i) {
+    const ProtocolDBusServiceInfo& info = protocol_dbus_services[i];
+    if (url.SchemeIs(info.scheme)) {
+      return CallDbusService(info, url);
+    }
+  }
+  return false;
+}
+
 void OpenExternal(const GURL& url) {
   if (url.SchemeIsHTTPOrHTTPS()) {
     LOG(INFO) << "Open in WebBrowser.";
@@ -31,6 +118,8 @@ void OpenExternal(const GURL& url) {
 
     if (base::LaunchProcess(argv, base::LaunchOptions(), &handle))
       base::EnsureProcessGetsReaped(handle);
+  } else if (!HandleExternalProtocol(url)) {
+    LOG(ERROR) << "Can not handle url: " << url.spec();
   }
 }
 
index 53c1fc4..be3a022 100644 (file)
@@ -5,7 +5,6 @@
 
 #include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate.h"
 
-#include "base/lazy_instance.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request.h"
+#include "xwalk/runtime/browser/runtime_platform_util.h"
 
-namespace {
-base::LazyInstance<xwalk::RuntimeResourceDispatcherHostDelegate>
-    g_runtime_resource_dispatcher_host_delegate = LAZY_INSTANCE_INITIALIZER;
-}
+#if defined(OS_ANDROID)
+#include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate_android.h"
+#endif
 
 namespace xwalk {
 
+// static
+scoped_ptr<RuntimeResourceDispatcherHostDelegate>
+RuntimeResourceDispatcherHostDelegate::Create() {
+#if defined(OS_ANDROID)
+  return make_scoped_ptr(
+      static_cast<RuntimeResourceDispatcherHostDelegate*>(
+            new RuntimeResourceDispatcherHostDelegateAndroid()));
+#else
+  return make_scoped_ptr(new RuntimeResourceDispatcherHostDelegate());
+#endif
+}
+
 RuntimeResourceDispatcherHostDelegate::RuntimeResourceDispatcherHostDelegate() {
 }
 
@@ -33,12 +44,6 @@ RuntimeResourceDispatcherHostDelegate::
 ~RuntimeResourceDispatcherHostDelegate() {
 }
 
-// static
-void RuntimeResourceDispatcherHostDelegate::ResourceDispatcherHostCreated() {
-  content::ResourceDispatcherHost::Get()->SetDelegate(
-      &g_runtime_resource_dispatcher_host_delegate.Get());
-}
-
 void RuntimeResourceDispatcherHostDelegate::RequestBeginning(
     net::URLRequest* request,
     content::ResourceContext* resource_context,
@@ -62,6 +67,7 @@ bool RuntimeResourceDispatcherHostDelegate::HandleExternalProtocol(
     const GURL& url,
     int child_id,
     int route_id) {
+  platform_util::OpenExternal(url);
   return true;
 }
 
index c15eea9..b3f5544 100644 (file)
@@ -16,6 +16,7 @@ class RuntimeResourceDispatcherHostDelegate
   virtual ~RuntimeResourceDispatcherHostDelegate();
 
   static void ResourceDispatcherHostCreated();
+  static scoped_ptr<RuntimeResourceDispatcherHostDelegate> Create();
 
   virtual void RequestBeginning(
       net::URLRequest* request,
index 6bbcc49..ba63063 100644 (file)
@@ -14,8 +14,6 @@
 #include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_controller.h"
-#include "content/public/browser/resource_dispatcher_host.h"
-#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/browser/resource_throttle.h"
 #include "content/public/common/url_constants.h"
 #include "xwalk/runtime/browser/android/xwalk_contents_io_thread_client.h"
 #include "xwalk/runtime/browser/android/xwalk_download_resource_throttle.h"
 #include "xwalk/runtime/browser/android/xwalk_login_delegate.h"
+#include "xwalk/runtime/browser/xwalk_content_browser_client.h"
 
 using content::BrowserThread;
 using navigation_interception::InterceptNavigationDelegate;
 using xwalk::XWalkContentsIoThreadClient;
 
 namespace {
-base::LazyInstance<xwalk::RuntimeResourceDispatcherHostDelegateAndroid>
-    g_runtime_resource_dispatcher_host_delegate_android =
-        LAZY_INSTANCE_INITIALIZER;
-
 void SetCacheControlFlag(
     net::URLRequest* request, int flag) {
   const int all_cache_control_flags = net::LOAD_BYPASS_CACHE |
@@ -93,7 +88,8 @@ IoThreadClientThrottle::IoThreadClientThrottle(int render_process_id,
 
 IoThreadClientThrottle::~IoThreadClientThrottle() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  g_runtime_resource_dispatcher_host_delegate_android.Get().
+  static_cast<RuntimeResourceDispatcherHostDelegateAndroid*>(
+      XWalkContentBrowserClient::Get()->resource_dispatcher_host_delegate())->
       RemovePendingThrottleOnIoThread(this);
 }
 
@@ -206,13 +202,6 @@ RuntimeResourceDispatcherHostDelegateAndroid::
     ~RuntimeResourceDispatcherHostDelegateAndroid() {
 }
 
-// static
-void RuntimeResourceDispatcherHostDelegateAndroid::
-ResourceDispatcherHostCreated() {
-  content::ResourceDispatcherHost::Get()->SetDelegate(
-      &g_runtime_resource_dispatcher_host_delegate_android.Get());
-}
-
 void RuntimeResourceDispatcherHostDelegateAndroid::RequestBeginning(
     net::URLRequest* request,
     content::ResourceContext* resource_context,
@@ -358,7 +347,9 @@ void RuntimeResourceDispatcherHostDelegateAndroid::OnIoThreadClientReady(
           &RuntimeResourceDispatcherHostDelegateAndroid::
           OnIoThreadClientReadyInternal,
           base::Unretained(
-              g_runtime_resource_dispatcher_host_delegate_android.Pointer()),
+              static_cast<RuntimeResourceDispatcherHostDelegateAndroid*>(
+                  XWalkContentBrowserClient::Get()->
+                      resource_dispatcher_host_delegate())),
           new_render_process_id, new_render_frame_id));
 }
 
@@ -372,7 +363,9 @@ void RuntimeResourceDispatcherHostDelegateAndroid::AddPendingThrottle(
           &RuntimeResourceDispatcherHostDelegateAndroid::
               AddPendingThrottleOnIoThread,
           base::Unretained(
-              g_runtime_resource_dispatcher_host_delegate_android.Pointer()),
+              static_cast<RuntimeResourceDispatcherHostDelegateAndroid*>(
+                  XWalkContentBrowserClient::Get()->
+                      resource_dispatcher_host_delegate())),
           render_process_id, render_frame_id, pending_throttle));
 }
 
index 0cb15e3..ce8dfb6 100644 (file)
@@ -8,7 +8,6 @@
 #include <map>
 #include <utility>
 
-#include "base/lazy_instance.h"
 #include "content/public/browser/content_browser_client.h"
 #include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate.h"
 
@@ -31,8 +30,6 @@ class RuntimeResourceDispatcherHostDelegateAndroid
   RuntimeResourceDispatcherHostDelegateAndroid();
   virtual ~RuntimeResourceDispatcherHostDelegateAndroid();
 
-  static void ResourceDispatcherHostCreated();
-
   virtual void RequestBeginning(
       net::URLRequest* request,
       content::ResourceContext* resource_context,
@@ -69,8 +66,6 @@ class RuntimeResourceDispatcherHostDelegateAndroid
                                  int render_frame_id,
                                  IoThreadClientThrottle* pending_throttle);
  private:
-  friend struct base::DefaultLazyInstanceTraits<
-      RuntimeResourceDispatcherHostDelegateAndroid>;
   // These methods must be called on IO thread.
   void OnIoThreadClientReadyInternal(int new_render_process_id,
                                      int new_render_frame_id);
diff --git a/src/xwalk/runtime/browser/runtime_ui_strategy.cc b/src/xwalk/runtime/browser/runtime_ui_strategy.cc
new file mode 100644 (file)
index 0000000..a2de96c
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/browser/runtime_ui_strategy.h"
+
+#include "base/command_line.h"
+#include "grit/xwalk_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image.h"
+#include "xwalk/runtime/browser/image_util.h"
+#include "xwalk/runtime/browser/runtime.h"
+#include "xwalk/runtime/common/xwalk_switches.h"
+
+namespace xwalk {
+namespace {
+#if !defined(OS_ANDROID)
+// The default size for web content area size.
+const int kDefaultWidth = 840;
+const int kDefaultHeight = 600;
+
+void ApplyWindowDefaultParams(Runtime* runtime,
+                              NativeAppWindow::CreateParams* params) {
+  if (!params->delegate)
+    params->delegate = runtime;
+  if (!params->web_contents)
+    params->web_contents = runtime->web_contents();
+  if (params->bounds.IsEmpty())
+    params->bounds = gfx::Rect(0, 0, kDefaultWidth, kDefaultHeight);
+
+  unsigned int fullscreen_options = runtime->fullscreen_options();
+  if (params->state == ui::SHOW_STATE_FULLSCREEN)
+    fullscreen_options |= Runtime::FULLSCREEN_FOR_LAUNCH;
+  else
+    fullscreen_options &= ~Runtime::FULLSCREEN_FOR_LAUNCH;
+  runtime->set_fullscreen_options(fullscreen_options);
+}
+#endif
+}  // namespace
+
+RuntimeUIStrategy::RuntimeUIStrategy() {}
+
+RuntimeUIStrategy::~RuntimeUIStrategy() {}
+
+void RuntimeUIStrategy::Show(
+    Runtime* runtime, const NativeAppWindow::CreateParams& params) {
+#if defined(OS_ANDROID)
+  NOTIMPLEMENTED();
+#else
+  NativeAppWindow::CreateParams effective_params(params);
+  ApplyWindowDefaultParams(runtime, &effective_params);
+
+  // Set the app icon if it is passed from command line.
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  gfx::Image app_icon;
+  if (command_line->HasSwitch(switches::kAppIcon)) {
+    base::FilePath icon_file =
+        command_line->GetSwitchValuePath(switches::kAppIcon);
+    app_icon = xwalk_utils::LoadImageFromFilePath(icon_file);
+  } else {
+    // Otherwise, use the default icon for Crosswalk app.
+    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+    app_icon = rb.GetNativeImageNamed(IDR_XWALK_ICON_48);
+  }
+
+  runtime->EnableTitleUpdatedNotification();
+
+  NativeAppWindow* window = NativeAppWindow::Create(effective_params);
+  runtime->set_window(window);
+
+  runtime->set_app_icon(app_icon);
+  window->Show();
+#endif
+}
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/runtime_ui_strategy.h b/src/xwalk/runtime/browser/runtime_ui_strategy.h
new file mode 100644 (file)
index 0000000..e01705c
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_BROWSER_RUNTIME_UI_STRATEGY_H_
+#define XWALK_RUNTIME_BROWSER_RUNTIME_UI_STRATEGY_H_
+
+#include "xwalk/runtime/browser/ui/native_app_window.h"
+
+namespace xwalk {
+class Runtime;
+
+class RuntimeUIStrategy {
+ public:
+  RuntimeUIStrategy();
+  virtual ~RuntimeUIStrategy();
+  virtual void Show(Runtime* runtime,
+                    const NativeAppWindow::CreateParams& params);
+};
+
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_BROWSER_RUNTIME_UI_STRATEGY_H_
diff --git a/src/xwalk/runtime/browser/tizen/render_view_context_menu_impl.cc b/src/xwalk/runtime/browser/tizen/render_view_context_menu_impl.cc
new file mode 100644 (file)
index 0000000..73bea4f
--- /dev/null
@@ -0,0 +1,258 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/browser/tizen/render_view_context_menu_impl.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/renderer_context_menu/views/toolkit_delegate_views.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/WebKit/public/web/WebContextMenuData.h"
+
+namespace xwalk {
+using blink::WebContextMenuData;
+
+namespace {
+
+enum {
+  // Nativation
+  CMD_BACK = 0,
+  CMD_FORWARD,
+  CMD_RELOAD,
+
+  // Link
+  CMD_OPEN_LINK_NEW_ACTIVITY,
+
+  // Edit
+  CMD_UNDO,
+  CMD_REDO,
+  CMD_CUT,
+  CMD_COPY,
+  CMD_PASTE,
+  CMD_PASTE_AND_MATCH_STYLE,
+  CMD_DELETE,
+  CMD_SELECT_ALL,
+  CMD_LAST,
+};
+
+// Max number of custom command ids allowd.
+const int kNumCustomCommandIds = 1000;
+
+// TODO(oshima): Move IDS for context menus to components/renderer_context_menu
+// and replace hardcoded strings below.
+void AppendPageItems(ui::SimpleMenuModel* menu_model) {
+  menu_model->AddItem(CMD_BACK, base::ASCIIToUTF16("Back"));
+  menu_model->AddItem(CMD_FORWARD, base::ASCIIToUTF16("Forward"));
+  menu_model->AddItem(CMD_RELOAD, base::ASCIIToUTF16("Reload"));
+  menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
+}
+
+void AppendLinkItems(const content::ContextMenuParams& params,
+                     ui::SimpleMenuModel* menu_model) {
+  if (!params.link_url.is_empty())
+    menu_model->AddItem(CMD_OPEN_LINK_NEW_ACTIVITY,
+                        base::ASCIIToUTF16("Open Link"));
+}
+
+void AppendEditableItems(ui::SimpleMenuModel* menu_model) {
+  menu_model->AddItem(CMD_UNDO, base::ASCIIToUTF16("Undo"));
+  menu_model->AddItem(CMD_REDO, base::ASCIIToUTF16("Redo"));
+  menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
+  menu_model->AddItem(CMD_CUT, base::ASCIIToUTF16("Cut"));
+  menu_model->AddItem(CMD_COPY, base::ASCIIToUTF16("Copy"));
+  menu_model->AddItem(CMD_PASTE, base::ASCIIToUTF16("Paste"));
+  menu_model->AddItem(CMD_PASTE_AND_MATCH_STYLE,
+                      base::ASCIIToUTF16("Paste as plain text"));
+  menu_model->AddItem(CMD_DELETE, base::ASCIIToUTF16("Delete"));
+  menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
+  menu_model->AddItem(CMD_SELECT_ALL, base::ASCIIToUTF16("Select All"));
+}
+
+}  // namespace
+
+RenderViewContextMenuImpl::RenderViewContextMenuImpl(
+    content::RenderFrameHost* render_frame_host,
+    const content::ContextMenuParams& params)
+    : RenderViewContextMenuBase(render_frame_host, params) {
+  SetContentCustomCommandIdRange(CMD_LAST, CMD_LAST + kNumCustomCommandIds);
+  // TODO(oshima): Support other types
+  set_content_type(
+      new ContextMenuContentType(source_web_contents_, params, true));
+  set_toolkit_delegate(scoped_ptr<ToolkitDelegate>(new ToolkitDelegateViews));
+}
+
+RenderViewContextMenuImpl::~RenderViewContextMenuImpl() {
+}
+
+void RenderViewContextMenuImpl::RunMenuAt(views::Widget* parent,
+                                          const gfx::Point& point,
+                                          ui::MenuSourceType type) {
+  static_cast<ToolkitDelegateViews*>(toolkit_delegate())
+      ->RunMenuAt(parent, point, type);
+}
+
+void RenderViewContextMenuImpl::InitMenu() {
+  RenderViewContextMenuBase::InitMenu();
+  bool needs_separator = false;
+  if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PAGE)) {
+    AppendPageItems(&menu_model_);
+    needs_separator = true;
+  }
+
+  if (content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_LINK)) {
+    if (needs_separator)
+      AddSeparator();
+    AppendLinkItems(params_, &menu_model_);
+    needs_separator = true;
+  }
+
+  if (content_type_->SupportsGroup(
+          ContextMenuContentType::ITEM_GROUP_EDITABLE)) {
+    if (needs_separator)
+      AddSeparator();
+    AppendEditableItems(&menu_model_);
+  }
+}
+
+void RenderViewContextMenuImpl::RecordShownItem(int id) {
+  // TODO(oshima): Imelement UMA stats. crbug.com/401673
+  NOTIMPLEMENTED();
+}
+
+void RenderViewContextMenuImpl::RecordUsedItem(int id) {
+  // TODO(oshima): Imelement UMA stats. crbug.com/401673
+  NOTIMPLEMENTED();
+}
+
+void RenderViewContextMenuImpl::NotifyMenuShown() {
+}
+
+void RenderViewContextMenuImpl::NotifyURLOpened(
+    const GURL& url,
+    content::WebContents* new_contents) {
+}
+
+bool RenderViewContextMenuImpl::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool RenderViewContextMenuImpl::IsCommandIdChecked(int command_id) const {
+  return false;
+}
+
+bool RenderViewContextMenuImpl::IsCommandIdEnabled(int command_id) const {
+  {
+    bool enabled = false;
+    if (RenderViewContextMenuBase::IsCommandIdKnown(command_id, &enabled))
+      return enabled;
+  }
+  switch (command_id) {
+    // Navigation
+    case CMD_BACK:
+      return source_web_contents_->GetController().CanGoBack();
+    case CMD_FORWARD:
+      return source_web_contents_->GetController().CanGoForward();
+    case CMD_RELOAD:
+      return true;
+
+    // Link
+    case CMD_OPEN_LINK_NEW_ACTIVITY:
+      return params_.link_url.is_valid();
+
+    // Editable
+    case CMD_UNDO:
+      return !!(params_.edit_flags & WebContextMenuData::CanUndo);
+
+    case CMD_REDO:
+      return !!(params_.edit_flags & WebContextMenuData::CanRedo);
+
+    case CMD_CUT:
+      return !!(params_.edit_flags & WebContextMenuData::CanCut);
+
+    case CMD_COPY:
+      return !!(params_.edit_flags & WebContextMenuData::CanCopy);
+
+    case CMD_PASTE:
+    case CMD_PASTE_AND_MATCH_STYLE:
+      return !!(params_.edit_flags & WebContextMenuData::CanPaste);
+
+    case CMD_DELETE:
+      return !!(params_.edit_flags & WebContextMenuData::CanDelete);
+
+    case CMD_SELECT_ALL:
+      return !!(params_.edit_flags & WebContextMenuData::CanSelectAll);
+  }
+  return false;
+}
+
+void RenderViewContextMenuImpl::ExecuteCommand(int command_id,
+                                               int event_flags) {
+  RenderViewContextMenuBase::ExecuteCommand(command_id, event_flags);
+  if (command_executed_)
+    return;
+  command_executed_ = true;
+  switch (command_id) {
+    // Navigation
+    case CMD_BACK:
+      source_web_contents_->GetController().GoBack();
+      break;
+    case CMD_FORWARD:
+      source_web_contents_->GetController().GoForward();
+      break;
+    case CMD_RELOAD:
+      source_web_contents_->GetController().Reload(true);
+      break;
+
+    // Link
+    case CMD_OPEN_LINK_NEW_ACTIVITY:
+      OpenURL(
+          params_.link_url,
+          params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
+          NEW_WINDOW,
+          ui::PAGE_TRANSITION_LINK);
+      break;
+
+    // Editable
+    case CMD_UNDO:
+      source_web_contents_->Undo();
+      break;
+
+    case CMD_REDO:
+      source_web_contents_->Redo();
+      break;
+
+    case CMD_CUT:
+      source_web_contents_->Cut();
+      break;
+
+    case CMD_COPY:
+      source_web_contents_->Copy();
+      break;
+
+    case CMD_PASTE:
+      source_web_contents_->Paste();
+      break;
+
+    case CMD_PASTE_AND_MATCH_STYLE:
+      source_web_contents_->PasteAndMatchStyle();
+      break;
+
+    case CMD_DELETE:
+      source_web_contents_->Delete();
+      break;
+
+    case CMD_SELECT_ALL:
+      source_web_contents_->SelectAll();
+      break;
+  }
+}
+
+void RenderViewContextMenuImpl::HandleAuthorizeAllPlugins() {
+}
+
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/tizen/render_view_context_menu_impl.h b/src/xwalk/runtime/browser/tizen/render_view_context_menu_impl.h
new file mode 100644 (file)
index 0000000..bac1c58
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_BROWSER_TIZEN_RENDER_VIEW_CONTEXT_MENU_IMPL_H_
+#define XWALK_RUNTIME_BROWSER_TIZEN_RENDER_VIEW_CONTEXT_MENU_IMPL_H_
+
+#include "components/renderer_context_menu/render_view_context_menu_base.h"
+
+namespace views {
+class Widget;
+}
+
+namespace gfx {
+class Point;
+}
+
+namespace xwalk {
+
+class RenderViewContextMenuImpl : public RenderViewContextMenuBase {
+ public:
+  RenderViewContextMenuImpl(content::RenderFrameHost* render_frame_host,
+                            const content::ContextMenuParams& params);
+  virtual ~RenderViewContextMenuImpl();
+
+  void RunMenuAt(views::Widget* parent,
+                 const gfx::Point& point,
+                 ui::MenuSourceType type);
+
+ private:
+  // RenderViewContextMenuBase:
+  void InitMenu() override;
+  void RecordShownItem(int id) override;
+  void RecordUsedItem(int id) override;
+  void NotifyMenuShown() override;
+  void NotifyURLOpened(const GURL& url,
+                               content::WebContents* new_contents) override;
+  void HandleAuthorizeAllPlugins() override;
+
+  // ui::SimpleMenuModel:
+  bool GetAcceleratorForCommandId(
+      int command_id,
+      ui::Accelerator* accelerator) override;
+  bool IsCommandIdChecked(int command_id) const override;
+  bool IsCommandIdEnabled(int command_id) const override;
+  void ExecuteCommand(int command_id, int event_flags) override;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuImpl);
+};
+
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_BROWSER_TIZEN_RENDER_VIEW_CONTEXT_MENU_IMPL_H_
diff --git a/src/xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.cc b/src/xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.cc
new file mode 100644 (file)
index 0000000..b21d4f0
--- /dev/null
@@ -0,0 +1,169 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.h"
+
+#include "components/web_modal/popup_manager.h"
+#include "components/web_modal/single_web_contents_dialog_manager.h"
+#include "components/web_modal/web_contents_modal_dialog_host.h"
+#include "components/web_modal/web_contents_modal_dialog_manager.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_view_delegate.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/window.h"
+#include "xwalk/application/browser/application.h"
+#include "xwalk/application/browser/application_system.h"
+#include "xwalk/application/browser/application_service.h"
+#include "xwalk/application/common/application_manifest_constants.h"
+#include "xwalk/application/common/manifest_handlers/tizen_setting_handler.h"
+#include "xwalk/runtime/browser/xwalk_runner.h"
+
+namespace xwalk {
+namespace {
+
+scoped_ptr<RenderViewContextMenuImpl> BuildMenu(
+    content::WebContents* web_contents,
+    const content::ContextMenuParams& params) {
+  scoped_ptr<RenderViewContextMenuImpl> menu;
+  content::RenderFrameHost* focused_frame = web_contents->GetFocusedFrame();
+  // If the frame tree does not have a focused frame at this point, do not
+  // bother creating RenderViewContextMenuViews.
+  // This happens if the frame has navigated to a different page before
+  // ContextMenu message was received by the current RenderFrameHost.
+  if (focused_frame) {
+    menu.reset(new RenderViewContextMenuImpl(focused_frame, params));
+    menu->Init();
+  }
+  return menu.Pass();
+}
+}  // namespace
+
+XWalkWebContentsViewDelegate::XWalkWebContentsViewDelegate(
+    content::WebContents* web_contents,
+    xwalk::application::ApplicationService* app_service)
+    : web_contents_(web_contents),
+      app_service_(app_service) {
+}
+
+XWalkWebContentsViewDelegate::~XWalkWebContentsViewDelegate() {
+}
+
+void XWalkWebContentsViewDelegate::ShowContextMenu(
+    content::RenderFrameHost* render_frame_host,
+    const content::ContextMenuParams& params) {
+  int render_process_id = render_frame_host->GetProcess()->GetID();
+  application::Application* app = XWalkRunner::GetInstance()->app_system()->
+      application_service()->GetApplicationByRenderHostID(render_process_id);
+  if (!app)
+    return;
+
+  application::TizenSettingInfo* info =
+      static_cast<application::TizenSettingInfo*>(
+          app->data()->GetManifestData(
+              application_widget_keys::kTizenSettingKey));
+  if (info && !info->context_menu_enabled())
+    return;
+
+  ShowMenu(BuildMenu(
+      content::WebContents::FromRenderFrameHost(render_frame_host), params));
+}
+
+content::WebDragDestDelegate*
+XWalkWebContentsViewDelegate::GetDragDestDelegate() {
+  return NULL;
+}
+
+void XWalkWebContentsViewDelegate::StoreFocus() {
+}
+
+void XWalkWebContentsViewDelegate::RestoreFocus() {
+}
+
+bool XWalkWebContentsViewDelegate::Focus() {
+  web_modal::PopupManager* popup_manager =
+      web_modal::PopupManager::FromWebContents(web_contents_);
+  if (popup_manager)
+    popup_manager->WasFocused(web_contents_);
+  return false;
+}
+
+void XWalkWebContentsViewDelegate::TakeFocus(bool reverse) {
+}
+
+void XWalkWebContentsViewDelegate::SizeChanged(const gfx::Size& size) {
+}
+
+void* XWalkWebContentsViewDelegate::CreateRenderWidgetHostViewDelegate(
+    content::RenderWidgetHost* render_widget_host) {
+  return NULL;
+}
+
+void XWalkWebContentsViewDelegate::ShowMenu(
+    scoped_ptr<RenderViewContextMenuImpl> menu) {
+  context_menu_.reset(menu.release());
+
+  if (!context_menu_.get())
+    return;
+
+  // Menus need a Widget to work. If we're not the active tab we won't
+  // necessarily be in a widget.
+  views::Widget* top_level_widget = GetTopLevelWidget();
+  if (!top_level_widget)
+    return;
+
+  const content::ContextMenuParams& params = context_menu_->params();
+  // Don't show empty menus.
+  if (context_menu_->menu_model().GetItemCount() == 0)
+    return;
+
+  gfx::Point screen_point(params.x, params.y);
+
+  // Convert from target window coordinates to root window coordinates.
+  aura::Window* target_window = GetActiveNativeView();
+  aura::Window* root_window = target_window->GetRootWindow();
+  aura::client::ScreenPositionClient* screen_position_client =
+      aura::client::GetScreenPositionClient(root_window);
+  if (screen_position_client) {
+    screen_position_client->ConvertPointToScreen(target_window,
+                                                 &screen_point);
+  }
+  // Enable recursive tasks on the message loop so we can get updates while
+  // the context menu is being displayed.
+  base::MessageLoop::ScopedNestableTaskAllower allow(
+      base::MessageLoop::current());
+  context_menu_->RunMenuAt(
+      top_level_widget, screen_point, params.source_type);
+}
+
+aura::Window* XWalkWebContentsViewDelegate::GetActiveNativeView() {
+  return web_contents_->GetFullscreenRenderWidgetHostView()
+      ? web_contents_->GetFullscreenRenderWidgetHostView()
+      ->GetNativeView()
+      : web_contents_->GetNativeView();
+}
+
+views::Widget* XWalkWebContentsViewDelegate::GetTopLevelWidget() {
+  return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView());
+}
+
+views::FocusManager* XWalkWebContentsViewDelegate::GetFocusManager() {
+  views::Widget* toplevel_widget = GetTopLevelWidget();
+  return toplevel_widget ? toplevel_widget->GetFocusManager() : NULL;
+}
+
+void XWalkWebContentsViewDelegate::SetInitialFocus() {
+  if (web_contents_->FocusLocationBarByDefault()) {
+    if (web_contents_->GetDelegate())
+      web_contents_->GetDelegate()->SetFocusToLocationBar(false);
+  } else {
+    web_contents_->Focus();
+  }
+}
+
+}  // namespace xwalk
diff --git a/src/xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.h b/src/xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.h
new file mode 100644 (file)
index 0000000..6c7a662
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_BROWSER_TIZEN_XWALK_WEB_CONTENTS_VIEW_DELEGATE_H_
+#define XWALK_RUNTIME_BROWSER_TIZEN_XWALK_WEB_CONTENTS_VIEW_DELEGATE_H_
+
+#include "content/public/browser/web_drag_dest_delegate.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view_delegate.h"
+#include "content/public/common/context_menu_params.h"
+#include "ui/views/widget/widget.h"
+#include "xwalk/application/browser/application_service.h"
+#include "xwalk/runtime/browser/tizen/render_view_context_menu_impl.h"
+
+namespace xwalk {
+
+class XWalkWebContentsViewDelegate : public content::WebContentsViewDelegate {
+ public:
+  XWalkWebContentsViewDelegate(
+      content::WebContents* web_contents,
+      xwalk::application::ApplicationService* app_service);
+  virtual ~XWalkWebContentsViewDelegate();
+
+  // Overridden from WebContentsViewDelegate:
+  void ShowContextMenu(content::RenderFrameHost* render_frame_host,
+                       const content::ContextMenuParams& params) override;
+  content::WebDragDestDelegate* GetDragDestDelegate() override;
+  void StoreFocus() override;
+  void RestoreFocus() override;
+  bool Focus() override;
+  void TakeFocus(bool reverse) override;
+  void SizeChanged(const gfx::Size& size) override;
+  virtual void* CreateRenderWidgetHostViewDelegate(
+      content::RenderWidgetHost* render_widget_host);
+
+#if defined(TOOLKIT_VIEWS) || defined(USE_AURA)
+  void ShowDisambiguationPopup(
+      const gfx::Rect& target_rect,
+      const SkBitmap& zoomed_bitmap,
+      const gfx::NativeView content,
+      const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
+      const base::Callback<void(ui::MouseEvent*)>& mouse_cb) override {
+    NOTIMPLEMENTED();
+  }
+
+  void HideDisambiguationPopup() override { NOTIMPLEMENTED(); }
+#endif
+
+ private:
+  aura::Window* GetActiveNativeView();
+  views::Widget* GetTopLevelWidget();
+  views::FocusManager* GetFocusManager();
+  void SetInitialFocus();
+  void ShowMenu(scoped_ptr<RenderViewContextMenuImpl> menu);
+
+  content::WebContents* web_contents_;
+  xwalk::application::ApplicationService* app_service_;
+  scoped_ptr<RenderViewContextMenuImpl> context_menu_;
+
+  DISALLOW_COPY_AND_ASSIGN(XWalkWebContentsViewDelegate);
+};
+}  // namespace xwalk
+
+#endif  // XWALK_RUNTIME_BROWSER_TIZEN_XWALK_WEB_CONTENTS_VIEW_DELEGATE_H_
index b1542f3..1cb3540 100644 (file)
@@ -231,6 +231,10 @@ bool NativeAppWindowViews::CanMaximize() const {
   return resizable_ && maximum_size_.IsEmpty();
 }
 
+bool NativeAppWindowViews::CanMinimize() const {
+  return true;
+}
+
 #if defined(OS_WIN)
 views::NonClientFrameView* NativeAppWindowViews::CreateNonClientFrameView(
     views::Widget* widget) {
index a234458..c971570 100644 (file)
@@ -78,6 +78,7 @@ class NativeAppWindowViews : public NativeAppWindow,
       gfx::Rect* bounds, ui::WindowShowState* show_state) const OVERRIDE;
   virtual bool CanResize() const OVERRIDE;
   virtual bool CanMaximize() const OVERRIDE;
+  virtual bool CanMinimize() const OVERRIDE;
 #if defined(OS_WIN)
   virtual views::NonClientFrameView* CreateNonClientFrameView(
       views::Widget* widget) OVERRIDE;
index c50493d..7b10e55 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "content/public/browser/browser_thread.h"
 #include "xwalk/application/browser/application.h"
 #include "xwalk/application/browser/application_service.h"
 #include "xwalk/application/browser/application_system.h"
@@ -15,6 +16,7 @@
 #include "xwalk/application/browser/application_service_provider_linux.h"
 #include "xwalk/application/browser/linux/running_application_object.h"
 #endif
+#include "xwalk/runtime/browser/runtime_defered_ui_strategy.h"
 
 namespace xwalk {
 
@@ -79,4 +81,21 @@ void XWalkAppExtensionBridge::ExtensionProcessCreated(
 #endif
 }
 
+void XWalkAppExtensionBridge::RenderChannelCreated(
+    int render_process_id) {
+  CHECK(app_system_);
+  application::ApplicationService *service =
+      app_system_->application_service();
+  application::Application *app =
+      service->GetApplicationByRenderHostID(render_process_id);
+  if (!app)
+    return;
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(
+          &RuntimeDeferedUIStrategy::ShowStoredRuntimes,
+          base::Unretained(ToRuntimeDeferedUIStrategy(app->ui_strategy()))));
+}
 }  // namespace xwalk
index 324dd32..73c019c 100644 (file)
@@ -42,6 +42,7 @@ class XWalkAppExtensionBridge
   virtual void ExtensionProcessCreated(
       int render_process_id,
       const IPC::ChannelHandle& channel_handle) OVERRIDE;
+  virtual void RenderChannelCreated(int render_process_id) OVERRIDE;
 
  private:
   application::ApplicationSystem* app_system_;
index d36821c..c5743e2 100644 (file)
@@ -17,6 +17,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/resource_context.h"
+#include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/main_function_params.h"
@@ -51,7 +52,6 @@
 #include "xwalk/runtime/browser/android/xwalk_cookie_access_policy.h"
 #include "xwalk/runtime/browser/android/xwalk_contents_client_bridge.h"
 #include "xwalk/runtime/browser/android/xwalk_web_contents_view_delegate.h"
-#include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate_android.h"
 #include "xwalk/runtime/browser/xwalk_browser_main_parts_android.h"
 #include "xwalk/runtime/common/android/xwalk_globals_android.h"
 #else
@@ -68,6 +68,7 @@
 #include "xwalk/application/common/application_manifest_constants.h"
 #include "xwalk/application/common/manifest_handlers/navigation_handler.h"
 #include "xwalk/runtime/browser/runtime_platform_util.h"
+#include "xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.h"
 #include "xwalk/runtime/browser/xwalk_browser_main_parts_tizen.h"
 #endif
 
@@ -168,6 +169,9 @@ XWalkContentBrowserClient::GetWebContentsViewDelegate(
     content::WebContents* web_contents) {
 #if defined(OS_ANDROID)
   return new XWalkWebContentsViewDelegate(web_contents);
+#elif defined(OS_TIZEN)
+  return new XWalkWebContentsViewDelegate(
+      web_contents, xwalk_runner_->app_system()->application_service());
 #else
   return NULL;
 #endif
@@ -348,12 +352,12 @@ content::BrowserPpapiHost*
   return NULL;
 }
 
-#if defined(OS_ANDROID)
 void XWalkContentBrowserClient::ResourceDispatcherHostCreated() {
-  RuntimeResourceDispatcherHostDelegateAndroid::
-  ResourceDispatcherHostCreated();
+  resource_dispatcher_host_delegate_ =
+      (RuntimeResourceDispatcherHostDelegate::Create()).Pass();
+  content::ResourceDispatcherHost::Get()->SetDelegate(
+      resource_dispatcher_host_delegate_.get());
 }
-#endif
 
 content::SpeechRecognitionManagerDelegate*
     XWalkContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
index 42bb3c3..6018266 100644 (file)
@@ -12,6 +12,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/common/main_function_params.h"
 #include "xwalk/runtime/browser/runtime_geolocation_permission_context.h"
+#include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate.h"
 
 namespace content {
 class BrowserContext;
@@ -136,8 +137,8 @@ class XWalkContentBrowserClient : public content::ContentBrowserClient {
   virtual content::BrowserPpapiHost* GetExternalBrowserPpapiHost(
       int plugin_process_id) OVERRIDE;
 
-#if defined(OS_ANDROID)
-  virtual void ResourceDispatcherHostCreated();
+#if defined(OS_ANDROID) || defined(OS_TIZEN)  || defined(OS_LINUX)
+  virtual void ResourceDispatcherHostCreated() OVERRIDE;
 #endif
 
   virtual void GetStoragePartitionConfigForSite(
@@ -153,6 +154,12 @@ class XWalkContentBrowserClient : public content::ContentBrowserClient {
 
   XWalkBrowserMainParts* main_parts() { return main_parts_; }
 
+#if defined(OS_ANDROID)
+  RuntimeResourceDispatcherHostDelegate* resource_dispatcher_host_delegate() {
+    return resource_dispatcher_host_delegate_.get();
+  }
+#endif
+
  private:
   XWalkRunner* xwalk_runner_;
   net::URLRequestContextGetter* url_request_context_getter_;
@@ -161,6 +168,9 @@ class XWalkContentBrowserClient : public content::ContentBrowserClient {
   XWalkBrowserMainParts* main_parts_;
   RuntimeContext* runtime_context_;
 
+  scoped_ptr<RuntimeResourceDispatcherHostDelegate>
+      resource_dispatcher_host_delegate_;
+
   DISALLOW_COPY_AND_ASSIGN(XWalkContentBrowserClient);
 };
 
index 4c4ba30..cd5186c 100644 (file)
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "xwalk/runtime/browser/image_util.h"
 #include "xwalk/runtime/browser/runtime.h"
+#include "xwalk/runtime/browser/runtime_ui_strategy.h"
 #include "xwalk/runtime/common/xwalk_notification_types.h"
 #include "xwalk/test/base/in_process_browser_test.h"
 #include "xwalk/test/base/xwalk_test_utils.h"
@@ -38,6 +39,21 @@ using xwalk::Runtime;
 using content::WebContents;
 using testing::_;
 
+namespace {
+Runtime* CreateWithDefaultWindow(
+    xwalk::RuntimeContext* runtime_context, const GURL& url,
+    Runtime::Observer* observer = NULL) {
+  Runtime* runtime = Runtime::Create(runtime_context, observer);
+  runtime->LoadURL(url);
+#if !defined(OS_ANDROID)
+  xwalk::RuntimeUIStrategy ui_strategy;
+  xwalk::NativeAppWindow::CreateParams params;
+  ui_strategy.Show(runtime, params);
+#endif
+  return runtime;
+}
+}  // namespace
+
 // Observer for NOTIFICATION_FULLSCREEN_CHANGED notifications.
 class FullscreenNotificationObserver
     : public content::WindowedNotificationObserver {
@@ -109,7 +125,7 @@ IN_PROC_BROWSER_TEST_F(XWalkRuntimeTest, CreateAndCloseRuntime) {
 
   // Create a new Runtime instance.
   GURL url(test_server()->GetURL("test.html"));
-  Runtime* new_runtime = Runtime::CreateWithDefaultWindow(
+  Runtime* new_runtime = CreateWithDefaultWindow(
       GetRuntimeContext(), url, runtime_registry());
   EXPECT_TRUE(url == new_runtime->web_contents()->GetURL());
   EXPECT_EQ(new_runtime, WaitForSingleNewRuntime());
@@ -135,7 +151,7 @@ IN_PROC_BROWSER_TEST_F(XWalkRuntimeTest, LoadURLAndClose) {
 
 IN_PROC_BROWSER_TEST_F(XWalkRuntimeTest, CloseNativeWindow) {
   GURL url(test_server()->GetURL("test.html"));
-  Runtime* new_runtime = Runtime::CreateWithDefaultWindow(
+  Runtime* new_runtime = CreateWithDefaultWindow(
       GetRuntimeContext(), url, runtime_registry());
   size_t len = runtimes().size();
   new_runtime->window()->Close();
@@ -151,7 +167,9 @@ IN_PROC_BROWSER_TEST_F(XWalkRuntimeTest, LaunchWithFullscreenWindow) {
 
   NativeAppWindow::CreateParams params;
   params.state = ui::SHOW_STATE_FULLSCREEN;
-  new_runtime->AttachWindow(params);
+  scoped_ptr<xwalk::RuntimeUIStrategy> ui_strategy(
+      new xwalk::RuntimeUIStrategy);
+  ui_strategy->Show(new_runtime, params);
   xwalk_test_utils::NavigateToURL(new_runtime, url);
 
   EXPECT_TRUE(new_runtime->window()->IsFullscreen());
index df898d1..5adbbfc 100644 (file)
@@ -10,6 +10,7 @@
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_platform_file.h"
+#include "third_party/skia/include/core/SkColor.h"
 
 // Singly-included section for enums and custom IPC traits.
 #ifndef XWALK_RUNTIME_COMMON_ANDROID_XWALK_RENDER_VIEW_MESSAGES_H_
@@ -84,6 +85,10 @@ IPC_MESSAGE_CONTROL2(XWalkViewMsg_SetOriginAccessWhitelist, // NOLINT(*)
                      std::string /* base url */,
                      std::string /* match pattern content*/)
 
+// Set the background  color
+IPC_MESSAGE_ROUTED1(XWalkViewMsg_SetBackgroundColor, // NOLINT(*)
+                    SkColor)
+
 //-----------------------------------------------------------------------------
 // RenderView messages
 // These are messages sent from the renderer to the browser process.
index 359316e..27a226f 100644 (file)
@@ -149,6 +149,7 @@ bool XWalkRenderViewExt::OnMessageReceived(const IPC::Message& message) {
     IPC_MESSAGE_HANDLER(XWalkViewMsg_ResetScrollAndScaleState,
                         OnResetScrollAndScaleState)
     IPC_MESSAGE_HANDLER(XWalkViewMsg_SetInitialPageScale, OnSetInitialPageScale)
+    IPC_MESSAGE_HANDLER(XWalkViewMsg_SetBackgroundColor, OnSetBackgroundColor)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -261,4 +262,10 @@ void XWalkRenderViewExt::OnSetInitialPageScale(double page_scale_factor) {
       page_scale_factor);
 }
 
+void XWalkRenderViewExt::OnSetBackgroundColor(SkColor c) {
+  if (!render_view() || !render_view()->GetWebView())
+    return;
+  render_view()->GetWebView()->setBaseBackgroundColor(c);
+}
+
 }  // namespace xwalk
index 44ae82d..78d5ae0 100644 (file)
@@ -8,6 +8,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "content/public/renderer/render_view_observer.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "third_party/WebKit/public/web/WebPermissionClient.h"
 
 namespace blink {
@@ -15,7 +16,7 @@ namespace blink {
 class WebNode;
 class WebURL;
 
-}  // namespace WebKit
+}  // namespace blink
 
 namespace xwalk {
 
@@ -49,7 +50,7 @@ class XWalkRenderViewExt : public content::RenderViewObserver {
 
   void UpdatePageScaleFactor();
 
-  bool capture_picture_enabled_;
+  void OnSetBackgroundColor(SkColor c);
 
   float page_scale_factor_;
 
index b98d39e..966fd58 100644 (file)
@@ -39,6 +39,7 @@ body {
   border-radius: 5px;
   height: 132px;
   width: 212px;
+  -webkit-background-size: cover;
   -webkit-transition-property: background-color, border-color;
   -webkit-transition: background-color 0.15s, 0.15s;
   -webkit-transition-delay: 0, 0;
@@ -114,6 +115,8 @@ function appendItem(itemObject) {
   var thumbnail = document.createElement('div');
   thumbnail.className = itemObject.devtoolsFrontendUrl ?
                         'thumbnail' : 'thumbnail connected';
+  if (itemObject.thumbnailUrl === undefined)
+    itemObject.thumbnailUrl = "/thumb/" + itemObject.id;
   thumbnail.style.cssText = 'background-image:url(' +
                         itemObject.thumbnailUrl +
                         ')';
index c974e65..cc3f9f7 100644 (file)
@@ -28,6 +28,7 @@ UDPSocketObject::UDPSocketObject()
       is_reading_(false),
       read_buffer_(new net::IOBuffer(kBufferSize)),
       write_buffer_(new net::IOBuffer(kBufferSize)),
+      write_buffer_size_(0),
       resolver_(net::HostResolver::CreateDefaultResolver(NULL)),
       single_resolver_(new net::SingleRequestHostResolver(resolver_.get())) {
   handler_.Register("init",
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnCreateWindowRequestedTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnCreateWindowRequestedTest.java
new file mode 100644 (file)
index 0000000..3a4e3ae
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.webkit.ValueCallback;
+
+import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.Feature;
+import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
+
+/**
+ * Test suite for OnCreateWindowRequested().
+ */
+public class OnCreateWindowRequestedTest extends XWalkViewTestBase {
+    private TestHelperBridge.OnCreateWindowRequestedHelper mOnCreateWindowRequestedHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mOnCreateWindowRequestedHelper = mTestHelperBridge.getOnCreateWindowRequestedHelper();
+
+        setUIClient(new XWalkUIClient(getXWalkView()){
+            @Override
+            public boolean onCreateWindowRequested(XWalkView view, InitiateBy initiator,
+                    ValueCallback<XWalkView> callback) {
+                Log.d("XWalkView", "onCreateWindowRequested: " + initiator);
+                XWalkView newView = new XWalkView(getActivity(), getActivity());
+
+                callback.onReceiveValue(newView);
+                mOnCreateWindowRequestedHelper.notifyCalled(newView);
+                return true;
+            }
+
+        });
+    }
+
+    @DisabledTest
+    public void testOnCreateWindowRequested() throws Throwable {
+        String fileContent = getFileContent("create_window_1.html");
+        int count = mOnCreateWindowRequestedHelper.getCallCount();
+
+        loadDataAsync(null, fileContent, "text/html", false);
+        clickOnElementId("new_window", null);
+        mOnCreateWindowRequestedHelper.waitForCallback(count);
+        assertNotNull(mOnCreateWindowRequestedHelper.getXWalkView());
+    }
+}
diff --git a/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnReceivedIconTest.java b/src/xwalk/test/android/core/javatests/src/org/xwalk/core/xwview/test/OnReceivedIconTest.java
new file mode 100644 (file)
index 0000000..46f1778
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.graphics.Bitmap;
+import android.os.Message;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.Feature;
+import org.xwalk.core.XWalkUIClient;
+import org.xwalk.core.XWalkView;
+
+/**
+ * Test suite for OnReceivedIcon().
+ */
+public class OnReceivedIconTest extends XWalkViewTestBase {
+    private TestHelperBridge.OnReceivedIconHelper mOnReceivedIconHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mOnReceivedIconHelper = mTestHelperBridge.getOnReceivedIconHelper();
+
+        setUIClient(new XWalkUIClient(getXWalkView()){
+            @Override
+            public void onIconAvailable(XWalkView view, String url, Message msg) {
+                Log.d("XWalkView", "onIconAvailable");
+                msg.sendToTarget();
+            }
+
+            @Override
+            public void onReceivedIcon(XWalkView view, String url, Bitmap icon) {
+                Log.d("XWalkView", "onReceivedIcon");
+                mOnReceivedIconHelper.notifyCalled(icon);
+            }
+        });
+    }
+
+    @DisabledTest
+    public void testOnReceivedIcon() throws Throwable {
+        String fileContent = getFileContent("favicon.html");
+        int count = mOnReceivedIconHelper.getCallCount();
+
+        loadDataAsync(null, fileContent, "text/html", false);
+        mOnReceivedIconHelper.waitForCallback(count);
+        assertNotNull(mOnReceivedIconHelper.getIcon());
+    }
+}
index a5bed93..61601c1 100644 (file)
@@ -5,6 +5,7 @@
 
 package org.xwalk.core.xwview.test;
 
+import android.graphics.Bitmap;
 import android.net.Uri;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -279,6 +280,34 @@ class TestHelperBridge {
         }
     }
 
+    public class OnCreateWindowRequestedHelper extends CallbackHelper {
+        private XWalkView mXWalkView;
+
+        public XWalkView getXWalkView() {
+            assert getCallCount() > 0;
+            return mXWalkView;
+        }
+
+        public void notifyCalled(XWalkView view) {
+            mXWalkView = view;
+            notifyCalled();
+        }
+    }
+
+    public class OnReceivedIconHelper extends CallbackHelper {
+        private Bitmap mIcon;
+
+        public Bitmap getIcon() {
+            assert getCallCount() > 0;
+            return mIcon;
+        }
+
+        public void notifyCalled(Bitmap icon) {
+            mIcon = icon;
+            notifyCalled();
+        }
+    }
+
     private String mChangedTitle;
     private LoadStatus mLoadStatus;
     private final OnPageStartedHelper mOnPageStartedHelper;
@@ -299,6 +328,8 @@ class TestHelperBridge {
     private final OpenFileChooserHelper mOpenFileChooserHelper;
     private final OnFullscreenToggledHelper mOnFullscreenToggledHelper;
     private final OverrideOrUnhandledKeyEventHelper mOverrideOrUnhandledKeyEventHelper;
+    private final OnCreateWindowRequestedHelper mOnCreateWindowRequestedHelper;
+    private final OnReceivedIconHelper mOnReceivedIconHelper;
 
     public TestHelperBridge() {
         mOnPageStartedHelper = new OnPageStartedHelper();
@@ -317,6 +348,8 @@ class TestHelperBridge {
         mOpenFileChooserHelper = new OpenFileChooserHelper();
         mOnFullscreenToggledHelper = new OnFullscreenToggledHelper();
         mOverrideOrUnhandledKeyEventHelper = new OverrideOrUnhandledKeyEventHelper();
+        mOnCreateWindowRequestedHelper = new OnCreateWindowRequestedHelper();
+        mOnReceivedIconHelper = new OnReceivedIconHelper();
     }
 
     public OnPageStartedHelper getOnPageStartedHelper() {
@@ -383,6 +416,14 @@ class TestHelperBridge {
         return mOverrideOrUnhandledKeyEventHelper;
     }
 
+    public OnCreateWindowRequestedHelper getOnCreateWindowRequestedHelper() {
+        return mOnCreateWindowRequestedHelper;
+    }
+
+    public OnReceivedIconHelper getOnReceivedIconHelper() {
+        return mOnReceivedIconHelper;
+    }
+
     public void onTitleChanged(String title) {
         mChangedTitle = title;
         mOnTitleUpdatedHelper.notifyCalled(title);
diff --git a/src/xwalk/test/android/data/create_window_1.html b/src/xwalk/test/android/data/create_window_1.html
new file mode 100644 (file)
index 0000000..6a82470
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Create Window 1</title>
+  <script type="text/javascript">
+    function createWindow() { window.open("create_window_2.html", "_blank", ""); }
+  </script>
+</head>
+<body>
+  <p>Create window by click <button id="new_window" onclick="createWindow();">button</button></p>
+</body>
+</html>
diff --git a/src/xwalk/test/android/data/create_window_2.html b/src/xwalk/test/android/data/create_window_2.html
new file mode 100644 (file)
index 0000000..2f65c0b
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Create Window 2</title>
+</head>
+<body>
+  <p>Create window by open <a id="new_window" href="new_window.html" target="_blank">link</a></p>
+</body>
+</html>
diff --git a/src/xwalk/test/android/data/favicon.html b/src/xwalk/test/android/data/favicon.html
new file mode 100644 (file)
index 0000000..6e60d4d
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Favicon</title>
+  <link rel="icon" href="icon.png" type="image/png" />
+</head>
+<body>
+  <p>The favicon will be shown by Toast</p>
+</body>
+</html>
diff --git a/src/xwalk/test/android/data/icon.png b/src/xwalk/test/android/data/icon.png
new file mode 100644 (file)
index 0000000..d94fd20
Binary files /dev/null and b/src/xwalk/test/android/data/icon.png differ
diff --git a/src/xwalk/test/android/data/new_window.html b/src/xwalk/test/android/data/new_window.html
new file mode 100644 (file)
index 0000000..3a52ae2
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>New Window</title>
+</head>
+<body>
+  <p>This is a new window</p>
+</body>
+</html>
index 9be97d0..c1b10b3 100644 (file)
@@ -50,6 +50,19 @@ base::LazyInstance<XWalkContentRendererClient>::Leaky
         g_xwalk_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
 #endif
 
+Runtime* CreateWithDefaultWindow(
+    xwalk::RuntimeContext* runtime_context, const GURL& url,
+    Runtime::Observer* observer = NULL) {
+  Runtime* runtime = Runtime::Create(runtime_context, observer);
+  runtime->LoadURL(url);
+#if !defined(OS_ANDROID)
+  xwalk::RuntimeUIStrategy ui_strategy;
+  xwalk::NativeAppWindow::CreateParams params;
+  ui_strategy.Show(runtime, params);
+#endif
+  return runtime;
+}
+
 }  // namespace
 
 RuntimeRegistry::RuntimeRegistry() {
@@ -148,7 +161,7 @@ void InProcessBrowserTest::RunTestOnMainThreadLoop() {
   // method, instead they should just create runtimes themselves
   // when needed and thus the 'runtime()' method should be removed
   // as well as 'runtime_' initialization below.
-  runtime_ = Runtime::CreateWithDefaultWindow(
+  runtime_ = CreateWithDefaultWindow(
           GetRuntimeContext(),
           GURL(), runtime_registry_.get());
   content::WaitForLoadStop(runtime_->web_contents());
index b5b4253..82d05f0 100644 (file)
@@ -5,6 +5,8 @@
 
 #include "xwalk/tizen/browser/media/browser_mediaplayer_manager.h"
 
+#include "content/browser/renderer_host/media/audio_renderer_host.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "xwalk/tizen/common/media/media_player_messages.h"
@@ -80,10 +82,15 @@ void BrowserMediaPlayerManager::OnInitialize(
     MediaPlayerID player_id,
     int process_id,
     const GURL& url) {
+  scoped_refptr<content::AudioRendererHost> audio_host =
+      static_cast<content::RenderProcessHostImpl*>(
+          render_frame_host_->GetProcess())->audio_renderer_host();
+
   // Create murphy resource for the given player id.
   if (resource_manager_ && resource_manager_->IsConnected()) {
-    MurphyResource* resource = new MurphyResource(this,
-        player_id, resource_manager_);
+    MurphyResource* resource = new MurphyResource(
+        this, player_id, audio_host->app_id(),
+        audio_host->app_class(), resource_manager_);
     RemoveMurphyResource(player_id);
     AddMurphyResource(resource);
   }
index 711c02a..2201ff5 100644 (file)
@@ -8,9 +8,7 @@
 
 namespace {
 
-const char kMediaApplicationClass[] = "player";
 const char kMediaStreamName[] = "audio_playback";
-const char kMediaRole[] = "browser";
 
 static void NotifyCallback(mrp_res_context_t* context,
     const mrp_res_resource_set_t* resource_set,
@@ -32,6 +30,8 @@ namespace tizen {
 MurphyResource::MurphyResource(
     BrowserMediaPlayerManager* manager,
     MediaPlayerID player_id,
+    const std::string& app_id,
+    const std::string& app_class,
     MurphyResourceManager* resource_manager)
     : manager_(manager),
       player_id_(player_id),
@@ -42,17 +42,20 @@ MurphyResource::MurphyResource(
     return;
 
   resource_set_ = mrp_res_create_resource_set(context,
-      kMediaApplicationClass, NotifyCallback, this);
+      app_class.c_str(), NotifyCallback, this);
   if (!resource_set_)
     return;
 
   mrp_res_resource_t* resource = mrp_res_create_resource(
       resource_set_, kMediaStreamName, true, true);
 
-  mrp_res_attribute_t* attr = mrp_res_get_attribute_by_name(
-      resource, "role");
+  mrp_res_attribute_t* attr = mrp_res_get_attribute_by_name(resource, "role");
   if (attr)
-    mrp_res_set_attribute_string(attr, kMediaRole);
+    mrp_res_set_attribute_string(attr, app_class.c_str());
+
+  attr = mrp_res_get_attribute_by_name(resource, "resource.set.appid");
+  if (attr)
+    mrp_res_set_attribute_string(attr, app_id.c_str());
 
   mrp_res_release_resource_set(resource_set_);
 }
index 895810d..4473aff 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef XWALK_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_H_
 #define XWALK_TIZEN_BROWSER_MEDIA_MURPHY_RESOURCE_H_
 
+#include <string>
+
 #include "xwalk/tizen/browser/media/murphy_resource_manager.h"
 
 namespace tizen {
@@ -15,6 +17,8 @@ class MurphyResource {
  public:
   MurphyResource(BrowserMediaPlayerManager* manager,
       MediaPlayerID player_id,
+      const std::string& app_id,
+      const std::string& app_calss,
       MurphyResourceManager* resource_manager);
   ~MurphyResource();
 
diff --git a/src/xwalk/tools/upstream_revision.py b/src/xwalk/tools/upstream_revision.py
new file mode 100755 (executable)
index 0000000..4586d0d
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright (c) 2014 Intel Corp. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+upstream_revision.py -- Upstream revision fetching utility.
+"""
+
+import optparse
+import os
+import sys
+
+
+def WriteIfChanged(file_name, contents):
+  """
+  Writes the specified contents to the specified file_name
+  iff the contents are different than the current contents.
+  """
+  try:
+    old_contents = open(file_name, 'r').read()
+  except EnvironmentError:
+    pass
+  else:
+    if contents == old_contents:
+      return
+    os.unlink(file_name)
+  open(file_name, 'w').write(contents)
+
+
+def main(argv=None):
+  if argv is None:
+    argv = sys.argv
+
+  parser = optparse.OptionParser(usage="upstream_revision.py [options]")
+  parser.add_option("-r", "--revision",
+                    help="The revision number.")
+  parser.add_option("-o", "--output", metavar="FILE",
+                    help="Write revision to FILE. ")
+  opts, _ = parser.parse_args(argv[1:])
+
+  contents = 'UPSTREAM_REVISION=%s' % opts.revision
+  WriteIfChanged(opts.output, contents)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
index fe20cd4..f2cadd6 100644 (file)
@@ -4,11 +4,6 @@
     'xwalk_version': '<!(python ../build/util/version.py -f VERSION -t "@MAJOR@.@MINOR@.@BUILD@.@PATCH@")',
     'chrome_version': '<!(python ../build/util/version.py -f ../chrome/VERSION -t "@MAJOR@.@MINOR@.@BUILD@.@PATCH@")',
     'conditions': [
-      ['OS=="linux"', {
-       'use_custom_freetype%': 1,
-      }, {
-       'use_custom_freetype%': 0,
-      }],
       ['OS=="win" or OS=="mac"', {
         'disable_nacl': 1,
       }],
         '../ui/base/ui_base.gyp:ui_base',
         '../ui/gl/gl.gyp:gl',
         '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
+        '../ui/snapshot/snapshot.gyp:snapshot',
         '../url/url.gyp:url_lib',
         '../v8/tools/gyp/v8.gyp:v8',
+        'generate_upstream_blink_version',
         'xwalk_application_lib',
         'xwalk_resources',
         'extensions/extensions.gyp:xwalk_extensions',
         'runtime/browser/runtime.h',
         'runtime/browser/runtime_context.cc',
         'runtime/browser/runtime_context.h',
+        'runtime/browser/runtime_defered_ui_strategy.cc',
+        'runtime/browser/runtime_defered_ui_strategy.h',
         'runtime/browser/runtime_download_manager_delegate.cc',
         'runtime/browser/runtime_download_manager_delegate.h',
         'runtime/browser/runtime_file_select_helper.cc',
         'runtime/browser/runtime_resource_dispatcher_host_delegate_android.h',
         'runtime/browser/runtime_select_file_policy.cc',
         'runtime/browser/runtime_select_file_policy.h',
+        'runtime/browser/runtime_ui_strategy.cc',
+        'runtime/browser/runtime_ui_strategy.h',
         'runtime/browser/runtime_url_request_context_getter.cc',
         'runtime/browser/runtime_url_request_context_getter.h',
         'runtime/browser/speech/speech_recognition_manager_delegate.cc',
             'sysapps/sysapps_resources.gyp:xwalk_sysapps_resources',
             'tizen/xwalk_tizen.gypi:xwalk_tizen_lib',
             '<(DEPTH)/third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
+            '../components/components.gyp:web_modal',
+            '../components/components.gyp:renderer_context_menu',
           ],
           'cflags': [
             '<!@(pkg-config --cflags libtzplatform-config)',
             'experimental/native_file_system/virtual_root_provider_tizen.cc',
             'runtime/browser/tizen/tizen_locale_listener.cc',
             'runtime/browser/tizen/tizen_locale_listener.h',
+            'runtime/browser/tizen/xwalk_web_contents_view_delegate.cc',
+            'runtime/browser/tizen/xwalk_web_contents_view_delegate.h',
+            'runtime/browser/tizen/render_view_context_menu_impl.cc',
+            'runtime/browser/tizen/render_view_context_menu_impl.h',
           ],
           'sources!':[
             'runtime/browser/runtime_platform_util_linux.cc',
+            'runtime/browser/android/xwalk_web_contents_view_delegate.cc',
+            'runtime/browser/android/xwalk_web_contents_view_delegate.h',
           ],
         }],
         ['OS=="android"',{
             '../base/allocator/allocator.gyp:allocator',
           ],
         }],  # os_posix==1 and OS != "mac" and use_allocator=="tcmalloc"
-        ['use_custom_freetype==1', {
-          'dependencies': [
-             '../third_party/freetype2/freetype2.gyp:freetype2',
-          ],
-        }],  # use_custom_freetype==1
         ['toolkit_views==1', {
           'dependencies': [
+            '../ui/events/events.gyp:events',
             '../ui/strings/ui_strings.gyp:ui_strings',
             '../ui/views/controls/webview/webview.gyp:webview',
             '../ui/views/views.gyp:views',
-            '../ui/views/views.gyp:views_test_support',
             '../ui/resources/ui_resources.gyp:ui_resources',
           ],
         }],  # toolkit_views==1
       ],
     },
     {
+      'target_name': 'generate_upstream_blink_version',
+      'type': 'none',
+      'actions': [
+        {
+          'action_name': 'generate_blink_upstream_version',
+          'inputs': [
+            '<(script)',
+            '<(upstream)',
+            '<(template)',
+          ],
+          'outputs': [
+            '<(SHARED_INTERMEDIATE_DIR)/blink_upstream_version.h',
+          ],
+          'action': ['python',
+                     '<(script)',
+                     '-f', '<(upstream)',
+                     '<(template)',
+                     '<@(_outputs)',
+          ],
+          'variables': {
+            'script': '<(DEPTH)/build/util/version.py',
+            'upstream': '<(DEPTH)/xwalk/build/UPSTREAM.blink',
+            'template': 'runtime/browser/blink_upstream_version.h.in',
+          },
+        },
+      ],
+    },
+    {
       'target_name': 'xwalk_resources',
       'type': 'none',
       'dependencies': [
index 8397bbb..7534956 100644 (file)
       ],
     },
     {
+      'target_name': 'adextension',
+      'type': 'none',
+      'dependencies': [
+        'xwalk_app_runtime_java',
+      ],
+      'variables': {
+        'java_in_dir': 'app/tools/android/test_data/extensions/adextension/',
+      },
+      'includes': ['../build/java.gypi'],
+    },
+    {
       'target_name': 'contactextension',
       'type': 'none',
       'dependencies': [
       'target_name': 'xwalk_packaging_tool_test',
       'type': 'none',
       'dependencies': [
+        'adextension',
         'contactextension',
         'myextension',
       ],
index bbc2ee9..8b78398 100644 (file)
         'is_test_apk': 1,
         'additional_input_paths': [
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/add_js_interface.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/create_window_1.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/create_window_2.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/echo.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/echoSync.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/favicon.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/file_chooser.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/framesEcho.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/fullscreen_enter_exit.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/fullscreen_togged.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/icon.png',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/index.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/js_modal_dialog.html',
+          '<(PRODUCT_DIR)/xwalk_xwview_test/assets/new_window.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/profile.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/scale_changed.html',
           '<(PRODUCT_DIR)/xwalk_xwview_test/assets/window.close.html',
           'destination': '<(PRODUCT_DIR)/xwalk_xwview_test/assets',
           'files': [
             'test/android/data/add_js_interface.html',
+            'test/android/data/create_window_1.html',
+            'test/android/data/create_window_2.html',
             'test/android/data/echo.html',
             'test/android/data/echoSync.html',
+            'test/android/data/favicon.html',
             'test/android/data/file_chooser.html',
             'test/android/data/framesEcho.html',
             'test/android/data/fullscreen_enter_exit.html',
             'test/android/data/fullscreen_togged.html',
+            'test/android/data/icon.png',
             'test/android/data/index.html',
             'test/android/data/js_modal_dialog.html',
+            'test/android/data/new_window.html',
             'test/android/data/profile.html',
             'test/android/data/scale_changed.html',
             'test/android/data/window.close.html',
         'resource_dir': 'runtime/android/sample/res',
         'native_lib_target': 'libxwalkcore',
         'additional_input_paths': [
+          '<(PRODUCT_DIR)/sample/assets/create_window_1.html',
+          '<(PRODUCT_DIR)/sample/assets/create_window_2.html',
           '<(PRODUCT_DIR)/sample/assets/echo.html',
+          '<(PRODUCT_DIR)/sample/assets/favicon.html',
+          '<(PRODUCT_DIR)/sample/assets/icon.png',
           '<(PRODUCT_DIR)/sample/assets/index.html',
           '<(PRODUCT_DIR)/sample/assets/manifest.json',
+          '<(PRODUCT_DIR)/sample/assets/new_window.html',
           '<(PRODUCT_DIR)/sample/assets/pause_timers.html',
           '<(PRODUCT_DIR)/sample/assets/xwalk.pak',
         ],
         {
           'destination': '<(PRODUCT_DIR)/sample/assets',
           'files': [
+            'runtime/android/sample/assets/create_window_1.html',
+            'runtime/android/sample/assets/create_window_2.html',
+            'runtime/android/sample/assets/favicon.html',
+            'runtime/android/sample/assets/icon.png',
             'runtime/android/sample/assets/index.html',
             'runtime/android/sample/assets/manifest.json',
+            'runtime/android/sample/assets/new_window.html',
             'runtime/android/sample/assets/pause_timers.html',
             'test/android/data/echo.html',
             '<(PRODUCT_DIR)/xwalk.pak',