%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+)
BuildRequires: python-xml
BuildRequires: perl
BuildRequires: which
+BuildRequires: yasm
BuildRequires: pkgconfig(ail)
BuildRequires: pkgconfig(alsa)
BuildRequires: pkgconfig(appcore-common)
-Duse_system_libexif=1 \
-Duse_system_libxml=1 \
-Duse_system_nspr=1 \
+-Duse_system_yasm=1 \
-Dshared_process_mode=1 \
-Denable_hidpi=1
-LASTCHANGE=88fc58a654d73e2df3dffc946077486c450f3bdb
+LASTCHANGE=52d4347d95a66afe54be98677b077fce0b7fd846
-LASTCHANGE=ed2bae8ced284782cbd55f1597e02d6ee621621b
+LASTCHANGE=a6caf4f53deee46eb41c31d38dc990964615b8e5
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;
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
#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"
// 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;
// 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);
};
#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"
// 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.
return;
}
+#if defined(OS_TIZEN)
+ stream_->SetMediaStreamProperties(handler_->app_id(), handler_->app_class());
+#endif
+
if (!stream_->Open()) {
DoStopCloseAndClearStream();
state_ = kError;
#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"
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() {}
};
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
#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"
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();
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);
};
if (!stream)
return false;
+#if defined(OS_TIZEN)
+ stream->SetMediaStreamProperties(app_id_, app_class_);
+#endif
+
if (!stream->Open()) {
stream->Close();
return false;
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
#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"
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,
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.
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)
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);
*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
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
// 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);
// 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"
// 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);
}
void DesktopWindowTreeHostWayland::Restore() {
+ g_delegate_ozone_wayland_->SetActiveWindow(this);
+
if (state_ & Normal)
return;
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
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();
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();
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));
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
* 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
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;
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();
InspectorFrontend::HeapProfiler* m_frontend;
unsigned m_nextUserInitiatedHeapSnapshotNumber;
OwnPtrWillBeMember<HeapStatsUpdateTask> m_heapStatsUpdateTask;
+ OwnPtrWillBeMember<HeapXDKUpdateTask> m_heapXDKUpdateTask;
};
} // namespace blink
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());
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()))
.setHitCount(node->GetHitCount())
.setCallUID(node->GetCallUid())
.setChildren(children.release())
+ .setLineTicks(lineTicks.release())
.setDeoptReason(node->GetBailoutReason())
.setId(node->GetNodeId());
return result.release();
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
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
{ "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" }
+ ]
+ }
]
},
{
/**
+ * 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.
*/
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;
+ }
};
*/
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();
#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))
}
+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());
}
}
+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();
}
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) {
void ProfilerEventsProcessor::StopSynchronously() {
- if (!running_) return;
- running_ = false;
+ if (!base::NoBarrier_AtomicExchange(&running_, 0)) return;
Join();
}
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.
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);
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);
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());
}
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();
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);
}
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);
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);
}
// 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.
ProfileGenerator* generator_;
Sampler* sampler_;
- bool running_;
+ base::Atomic32 running_;
// Sampling period in microseconds.
const base::TimeDelta period_;
UnboundQueue<CodeEventsContainer> events_buffer_;
#include "src/allocation-tracker.h"
#include "src/heap-snapshot-generator-inl.h"
+#include "src/xdk-allocation.h"
namespace v8 {
namespace internal {
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;
}
+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();
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);
}
}
if (!allocation_tracker_.is_empty()) {
allocation_tracker_->AllocationEvent(addr, size);
}
+ if (!allocation_tracker_xdk_.is_empty()) {
+ allocation_tracker_xdk_->OnAlloc(addr, size);
+ }
}
namespace internal {
class HeapSnapshot;
+class HeapEventXDK;
class HeapProfiler {
public:
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);
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);
unsigned next_snapshot_uid_;
List<v8::HeapProfiler::WrapperInfoCallback> wrapper_callbacks_;
SmartPointer<AllocationTracker> allocation_tracker_;
+ SmartPointer<XDKAllocationTracker> allocation_tracker_xdk_;
bool is_tracking_object_moves_;
};
int HeapEntry::index() const {
- return static_cast<int>(this - &snapshot_->entries().first());
+ return static_cast<int>(this - &entries_->first());
}
const int HeapEntry::kNoEntry = -1;
HeapEntry::HeapEntry(HeapSnapshot* snapshot,
+ const List<HeapEntry>* entries,
Type type,
const char* name,
SnapshotObjectId id,
children_index_(-1),
self_size_(self_size),
snapshot_(snapshot),
+ entries_(entries),
name_(name),
id_(id),
trace_node_id_(trace_node_id) { }
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
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();
}
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) {
}
-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());
// 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
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());
+ }
}
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));
+ }
}
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);
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);
}
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) {
}
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;
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_);
+ }
}
namespace internal {
class AllocationTracker;
+class XDKAllocationTracker;
class AllocationTraceNode;
class HeapEntry;
class HeapSnapshot;
HeapEntry() { }
HeapEntry(HeapSnapshot* snapshot,
+ const List<HeapEntry>* entries,
Type type,
const char* name,
SnapshotObjectId id,
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
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();
// 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);
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:
int progress_counter_;
int progress_total_;
Heap* heap_;
+ SnapshotFiller* filler_;
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
};
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),
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) {
}
+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 = "";
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;
// 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);
}
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;
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;
}
// 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 &&
// 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);
}
}
}
+ 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 ||
}
}
- 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;
*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();
// 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
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_); }
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;
List<OffsetRange>* no_frame_ranges_;
const char* bailout_reason_;
JITLineInfoTable* line_info_;
+ Address instruction_start_;
DISALLOW_COPY_AND_ASSIGN(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);
// Called from profile generator thread.
void AddPathToCurrentProfiles(base::TimeTicks timestamp,
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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
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);
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);
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());
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();
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) {
#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;
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);
+}
'../../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', {
# 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'
'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
}
]
+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.
# -------------------------------------------------
-MAJOR=10
+MAJOR=11
MINOR=39
-BUILD=234
+BUILD=244
PATCH=0
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;
private boolean mShownNotFoundDialog = false;
- private BroadcastReceiver mReceiver;
-
private boolean mRemoteDebugging = false;
private boolean mUseAnimatableView = false;
@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();
@Override
public void onDestroy() {
- unregisterReceiver(mReceiver);
if (mExtensionManager != null) mExtensionManager.onDestroy();
super.onDestroy();
}
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;
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() {
@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();
}
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;
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;
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
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:
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)
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',
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'))
--- /dev/null
+<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>
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//This is a dummy file
--- /dev/null
+{
+ "name": "Ad",
+ "class": "com.example.extension.AdExtension",
+ "jsapi": "adextension.js",
+ "manifest": "AndroidManifest.xml"
+}
--- /dev/null
+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);
+ }
+}
#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)
security_mode_enabled_(false),
runtime_context_(runtime_context),
observer_(NULL),
+ ui_strategy_(new RuntimeDeferedUIStrategy),
remote_debugging_enabled_(false),
weak_factory_(this) {
DCHECK(runtime_context_);
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;
}
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);
}
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,
#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 {
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();
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();
}
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,
#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*>(
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);
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);
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
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_;
};
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);
#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
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";
#if defined(OS_TIZEN)
extern const char kTizenAppIdKey[];
extern const char kIcon128Key[];
+ extern const char kXWalkMediaAppClass[];
#endif
} // namespace application_manifest_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[];
// 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.
"_generated_main_document.html";
const base::FilePath::CharType kCookieDatabaseFilename[] =
FILE_PATH_LITERAL("ApplicationCookies");
+const char kTizenWebAPIVersion[] = "2.2";
} // namespace application
} // namespace xwalk
// 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.
// 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
// 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.
#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 {
" 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;
}
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;
"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;
}
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 {
// 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;
char* install_path = NULL;
char* uninstall_id = NULL;
-char* reinstall_path = NULL;
+char* reinstall_id = NULL;
char* operation_key = NULL;
int quiet = 0;
"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,
}
} 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;
}
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);
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) {
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 =
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;
}
#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>
// 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"
#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;
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) {
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() {
#define XWALK_APPLICATION_TOOLS_TIZEN_XWALK_PACKAGE_INSTALLER_H_
#include <string>
+
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
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();
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_;
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[];
#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
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;
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(
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;
}
}
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();
}
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, "/"));
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;
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;
}
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,
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);
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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_
'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
// 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) {
err = getgrgid_r(getgid(), &grp, buffer, len, ¤t_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;
}
err = getgrgid_r(getgid(), &grp, buffer, len, ¤t_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;
}
is_extension_process_channel_ready_ = true;
ep_rp_channel_handle_ = handle;
ReplyChannelHandleToRenderProcess();
+ if (delegate_)
+ delegate_->OnRenderChannelCreated(render_process_host_->GetID());
}
void XWalkExtensionProcessHost::ReplyChannelHandleToRenderProcess() {
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() {}
};
extension_name, perm_table);
}
+void XWalkExtensionService::OnRenderChannelCreated(int render_process_id) {
+ CHECK(delegate_);
+ delegate_->RenderChannelCreated(render_process_id);
+}
+
} // namespace extensions
} // namespace xwalk
virtual void ExtensionProcessCreated(
int render_process_id,
const IPC::ChannelHandle& channel_handle) {}
+ virtual void RenderChannelCreated(int render_process_id) {}
protected:
~Delegate() {}
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,
}
bool RegisterXWalkExtensionAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
} // namespace extensions
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()
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);
%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+)
BuildRequires: python-xml
BuildRequires: perl
BuildRequires: which
+BuildRequires: yasm
BuildRequires: pkgconfig(ail)
BuildRequires: pkgconfig(alsa)
BuildRequires: pkgconfig(appcore-common)
-Duse_system_libexif=1 \
-Duse_system_libxml=1 \
-Duse_system_nspr=1 \
+-Duse_system_yasm=1 \
-Dshared_process_mode=1 \
-Denable_hidpi=1
}
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.");
}
public void loadUrl(String url, String data) {
+ if (mNativeContent == 0) return;
+
if ((url == null || url.isEmpty()) &&
(data == null || data.isEmpty())) {
return;
}
public void reload(int mode) {
+ if (mNativeContent == 0) return;
+
switch (mode) {
case XWalkViewInternal.RELOAD_IGNORE_CACHE:
mNavigationController.reloadIgnoringCache(true);
}
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) {
}
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);
}
}
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();
}
}
public void stopLoading() {
+ if (mNativeContent == 0) return;
mWebContents.stop();
mContentsClientBridge.onStopLoading();
}
// 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()) {
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);
// For instrumentation test.
public void installWebContentsObserverForTest(XWalkContentsClient contentClient) {
+ if (mNativeContent == 0) return;
contentClient.installWebContentsObserver(mContentViewCore.getWebContents());
}
}
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;
}
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;
@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);
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;
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);
}
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);
// 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;
}
// 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) {
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;
}
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) {
/**
* 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.
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;
}
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.
@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);
}
// TODO(yongsheng): make it static?
@XWalkAPI
public String getAPIVersion() {
- return "3.0";
+ return "4.1";
}
/**
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
/**
* 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);
}
/**
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();
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;
+ }
}
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;
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;
MessagingSmsManager(Activity activity, Messaging messaging) {
mActivity = new WeakReference<Activity>(activity);
mMessagingHandler = messaging;
+ mUUID = UUID.randomUUID().toString();
}
private boolean checkService(String serviceID) {
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,
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,
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);
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));
serviceID: serviceID
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
SmsManager.prototype.clear = function(serviceID) {
serviceID: serviceID
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
SmsManager.prototype.segmentInfo = function(text, serviceID) {
serviceID: serviceID
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
var sms = new SmsManager();
options: options
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
exports.findConversations = function(groupBy, filter, options) {
messageID: messageID
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
exports.deleteMessage = function(type, messageID) {
messageID: messageID
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
exports.deleteConversation = function(type, conversationID) {
conversationID: conversationID
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
exports.markMessageRead = function(type, messageID, value) {
value: value
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
exports.markConversationRead = function(type, conversationID, value) {
value: value
}
}
- return postMessage(_msg);
+ return createPromise(_msg);
}
</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" >
--- /dev/null
+<!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>
--- /dev/null
+<!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>
--- /dev/null
+<!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>
--- /dev/null
+<!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>
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.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);
+ }
+}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.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);
+ }
+}
client_bridge->OnWebLayoutPageScaleFactorChanged(page_scale_factor);
}
+void XWalkRenderViewHostExt::SetBackgroundColor(SkColor c) {
+ DCHECK(CalledOnValidThread());
+ Send(new XWalkViewMsg_SetBackgroundColor(web_contents()->GetRoutingID(), c));
+}
+
} // namespace xwalk
// 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,
}
bool RegisterXWalkContent(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
namespace {
}
}
+// 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
jobject obj,
jstring path,
jstring manifest);
+ void SetBackgroundColor(JNIEnv* env, jobject obj, jint color);
// Geolocation API support
void ShowGeolocationPrompt(const GURL& origin,
}
bool RegisterXWalkContentsClientBridge(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
} // namespace xwalk
#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"
#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"
// 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) {
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 {
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);
};
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() {
// 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() {
// 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);
}
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
~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();
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);
};
}
bool RegisterXWalkHttpAuthHandler(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
} // namespace xwalk
}
bool RegisterXWalkPathHelper(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
} // namespace xwalk
}
bool RegisterXWalkSettings(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
} // namespace xwalk
}
bool RegisterXWalkViewDelegate(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
} // namespace xwalk
--- /dev/null
+// 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@"
#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:
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();
#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 {
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_;
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_;
};
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() {
}
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;
}
}
XWalkDevToolsDelegate::XWalkDevToolsDelegate(RuntimeContext* runtime_context)
- : runtime_context_(runtime_context) {
+ : runtime_context_(runtime_context),
+ weak_factory_(this) {
}
XWalkDevToolsDelegate::~XWalkDevToolsDelegate() {
}
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())));
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);
#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"
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);
};
#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"
#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,
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)
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);
}
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) {
//////////////////////////////////////////////////////
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;
}
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(
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(¶ms);
- root_window_ = NativeAppWindow::Create(params);
-}
-
-void Runtime::SetRootWindow(NativeAppWindow* window) {
- root_window_= window;
-}
-
-#endif
} // namespace xwalk
#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"
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();
}
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();
// 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_;
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_;
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
}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/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
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_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_
return true;
}
+void OpenExternal(const GURL& url) {
+ NOTIMPLEMENTED();
+}
+
} // namespace platform_util
#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 {
// 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.";
if (base::LaunchProcess(argv, base::LaunchOptions(), &handle))
base::EnsureProcessGetsReaped(handle);
+ } else if (!HandleExternalProtocol(url)) {
+ LOG(ERROR) << "Can not handle url: " << url.spec();
}
}
#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() {
}
~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,
const GURL& url,
int child_id,
int route_id) {
+ platform_util::OpenExternal(url);
return true;
}
virtual ~RuntimeResourceDispatcherHostDelegate();
static void ResourceDispatcherHostCreated();
+ static scoped_ptr<RuntimeResourceDispatcherHostDelegate> Create();
virtual void RequestBeginning(
net::URLRequest* request,
#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 |
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);
}
~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,
&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));
}
&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));
}
#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"
RuntimeResourceDispatcherHostDelegateAndroid();
virtual ~RuntimeResourceDispatcherHostDelegateAndroid();
- static void ResourceDispatcherHostCreated();
-
virtual void RequestBeginning(
net::URLRequest* request,
content::ResourceContext* resource_context,
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);
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/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
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_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_
--- /dev/null
+// 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
--- /dev/null
+// 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_
--- /dev/null
+// 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
--- /dev/null
+// 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_
return resizable_ && maximum_size_.IsEmpty();
}
+bool NativeAppWindowViews::CanMinimize() const {
+ return true;
+}
+
#if defined(OS_WIN)
views::NonClientFrameView* NativeAppWindowViews::CreateNonClientFrameView(
views::Widget* widget) {
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;
#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"
#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 {
#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
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_;
#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"
#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
#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
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
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() {
#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;
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(
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_;
XWalkBrowserMainParts* main_parts_;
RuntimeContext* runtime_context_;
+ scoped_ptr<RuntimeResourceDispatcherHostDelegate>
+ resource_dispatcher_host_delegate_;
+
DISALLOW_COPY_AND_ASSIGN(XWalkContentBrowserClient);
};
#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"
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 {
// 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());
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();
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());
#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_
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.
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;
page_scale_factor);
}
+void XWalkRenderViewExt::OnSetBackgroundColor(SkColor c) {
+ if (!render_view() || !render_view()->GetWebView())
+ return;
+ render_view()->GetWebView()->setBaseBackgroundColor(c);
+}
+
} // namespace xwalk
#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 {
class WebNode;
class WebURL;
-} // namespace WebKit
+} // namespace blink
namespace xwalk {
void UpdatePageScaleFactor();
- bool capture_picture_enabled_;
+ void OnSetBackgroundColor(SkColor c);
float page_scale_factor_;
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;
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 +
')';
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",
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import 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());
+ }
+}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.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());
+ }
+}
package org.xwalk.core.xwview.test;
+import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import android.view.KeyEvent;
}
}
+ 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;
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();
mOpenFileChooserHelper = new OpenFileChooserHelper();
mOnFullscreenToggledHelper = new OnFullscreenToggledHelper();
mOverrideOrUnhandledKeyEventHelper = new OverrideOrUnhandledKeyEventHelper();
+ mOnCreateWindowRequestedHelper = new OnCreateWindowRequestedHelper();
+ mOnReceivedIconHelper = new OnReceivedIconHelper();
}
public OnPageStartedHelper getOnPageStartedHelper() {
return mOverrideOrUnhandledKeyEventHelper;
}
+ public OnCreateWindowRequestedHelper getOnCreateWindowRequestedHelper() {
+ return mOnCreateWindowRequestedHelper;
+ }
+
+ public OnReceivedIconHelper getOnReceivedIconHelper() {
+ return mOnReceivedIconHelper;
+ }
+
public void onTitleChanged(String title) {
mChangedTitle = title;
mOnTitleUpdatedHelper.notifyCalled(title);
--- /dev/null
+<!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>
--- /dev/null
+<!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>
--- /dev/null
+<!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>
--- /dev/null
+<!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>
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() {
// 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());
#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"
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);
}
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,
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),
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_);
}
#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 {
public:
MurphyResource(BrowserMediaPlayerManager* manager,
MediaPlayerID player_id,
+ const std::string& app_id,
+ const std::string& app_calss,
MurphyResourceManager* resource_manager);
~MurphyResource();
--- /dev/null
+#!/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())
'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': [
],
},
{
+ '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',
],
'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',