mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge last green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
commit
e671bf9cd2
@ -74,7 +74,7 @@ static const NSString* AXRoles [] = {
|
||||
NSAccessibilityGroupRole, // ROLE_CELL
|
||||
@"AXLink", // ROLE_LINK. 10.4+ the attr first define in SDK 10.4, so we define it here too. ROLE_LINK
|
||||
@"AXHelpTag", // ROLE_HELPBALLOON
|
||||
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unusued on OS X
|
||||
NSAccessibilityUnknownRole, // ROLE_CHARACTER. unused on OS X
|
||||
NSAccessibilityListRole, // ROLE_LIST
|
||||
NSAccessibilityRowRole, // ROLE_LISTITEM
|
||||
NSAccessibilityOutlineRole, // ROLE_OUTLINE
|
||||
|
@ -932,6 +932,8 @@ xpicleanup@BIN_SUFFIX@
|
||||
#endif
|
||||
components/txEXSLTRegExFunctions.js
|
||||
components/Weave.js
|
||||
components/Webapps.js
|
||||
components/Webapps.manifest
|
||||
components/WebContentConverter.js
|
||||
defaults/autoconfig/platform.js
|
||||
defaults/autoconfig/prefcalls.js
|
||||
@ -1057,6 +1059,7 @@ xpicleanup@BIN_SUFFIX@
|
||||
modules/tabview/AllTabs.jsm
|
||||
modules/tabview/groups.jsm
|
||||
modules/tabview/utils.jsm
|
||||
modules/Webapps.jsm
|
||||
modules/WindowDraggingUtils.jsm
|
||||
#ifdef XP_WIN
|
||||
modules/WindowsJumpLists.jsm
|
||||
@ -1147,6 +1150,7 @@ xpicleanup@BIN_SUFFIX@
|
||||
components/directory.xpt
|
||||
components/docshell.xpt
|
||||
components/dom.xpt
|
||||
components/dom_apps.xpt
|
||||
components/dom_base.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
components/dom_telephony.xpt
|
||||
|
@ -1999,6 +1999,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
LOG(PR_LOG_DEBUG, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
|
||||
|
||||
if (!decoder->Init(this)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to init cloned decoder %p", this, decoder.get()));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -2010,6 +2011,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
|
||||
nsMediaStream* stream = originalStream->CloneData(decoder);
|
||||
if (!stream) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -2017,6 +2019,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal)
|
||||
|
||||
nsresult rv = decoder->Load(stream, nsnull, aOriginal);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to load decoder/stream for decoder %p", this, decoder.get()));
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -193,6 +193,7 @@ nsresult nsBuiltinDecoder::Load(nsMediaStream* aStream,
|
||||
|
||||
nsresult rv = aStream->Open(aStreamListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
|
||||
delete aStream;
|
||||
return rv;
|
||||
}
|
||||
@ -245,6 +246,7 @@ nsresult nsBuiltinDecoder::ScheduleStateMachineThread()
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
NS_ASSERTION(mDecoderStateMachine,
|
||||
"Must have state machine to start state machine thread");
|
||||
NS_ENSURE_STATE(mDecoderStateMachine);
|
||||
|
||||
if (mShuttingDown)
|
||||
return NS_OK;
|
||||
@ -258,6 +260,7 @@ nsresult nsBuiltinDecoder::Play()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
NS_ASSERTION(mDecoderStateMachine != nsnull, "Should have state machine.");
|
||||
nsresult res = ScheduleStateMachineThread();
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
if (mPlayState == PLAY_STATE_SEEKING) {
|
||||
@ -832,29 +835,19 @@ void nsBuiltinDecoder::ChangeState(PlayState aState)
|
||||
}
|
||||
|
||||
mPlayState = aState;
|
||||
switch (aState) {
|
||||
case PLAY_STATE_PAUSED:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_PLAYING:
|
||||
mDecoderStateMachine->Play();
|
||||
break;
|
||||
case PLAY_STATE_SEEKING:
|
||||
mDecoderStateMachine->Seek(mRequestedSeekTime);
|
||||
mRequestedSeekTime = -1.0;
|
||||
break;
|
||||
case PLAY_STATE_LOADING:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_START:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_ENDED:
|
||||
/* No action needed */
|
||||
break;
|
||||
case PLAY_STATE_SHUTDOWN:
|
||||
/* No action needed */
|
||||
break;
|
||||
if (mDecoderStateMachine) {
|
||||
switch (aState) {
|
||||
case PLAY_STATE_PLAYING:
|
||||
mDecoderStateMachine->Play();
|
||||
break;
|
||||
case PLAY_STATE_SEEKING:
|
||||
mDecoderStateMachine->Seek(mRequestedSeekTime);
|
||||
mRequestedSeekTime = -1.0;
|
||||
break;
|
||||
default:
|
||||
/* No action needed */
|
||||
break;
|
||||
}
|
||||
}
|
||||
mReentrantMonitor.NotifyAll();
|
||||
}
|
||||
@ -973,7 +966,9 @@ void nsBuiltinDecoder::Resume(bool aForceBuffering)
|
||||
}
|
||||
if (aForceBuffering) {
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mDecoderStateMachine->StartBuffering();
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->StartBuffering();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "nsTimeRanges.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StdInt.h"
|
||||
@ -229,6 +230,17 @@ public:
|
||||
return mStateMachineThread;
|
||||
}
|
||||
|
||||
// Requests that a decode thread be created for aStateMachine. The thread
|
||||
// may be created immediately, or after some delay, once a thread becomes
|
||||
// available. The request can be cancelled using CancelCreateDecodeThread().
|
||||
// It's the callers responsibility to not call this more than once for any
|
||||
// given state machine.
|
||||
nsresult RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
|
||||
|
||||
// Cancels a request made by RequestCreateDecodeThread to create a decode
|
||||
// thread for aStateMachine.
|
||||
nsresult CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine);
|
||||
|
||||
// Maximum number of active decode threads allowed. When more
|
||||
// than this number are active the thread creation will fail.
|
||||
static const PRUint32 MAX_DECODE_THREADS = 25;
|
||||
@ -238,16 +250,17 @@ public:
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
PRUint32 GetDecodeThreadCount();
|
||||
|
||||
// Keep track of the fact that a decode thread was created.
|
||||
// Call on any thread. Holds the internal monitor so don't
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
void NoteDecodeThreadCreated();
|
||||
|
||||
// Keep track of the fact that a decode thread was destroyed.
|
||||
// Call on any thread. Holds the internal monitor so don't
|
||||
// call with any other monitor held to avoid deadlock.
|
||||
void NoteDecodeThreadDestroyed();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Returns true if aStateMachine has a pending request for a
|
||||
// decode thread.
|
||||
bool IsQueued(nsBuiltinDecoderStateMachine* aStateMachine);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Holds global instance of StateMachineTracker.
|
||||
// Writable on main thread only.
|
||||
@ -271,6 +284,10 @@ private:
|
||||
// only, read from the decoder threads. Synchronized via
|
||||
// the mMonitor.
|
||||
nsIThread* mStateMachineThread;
|
||||
|
||||
// Queue of state machines waiting for decode threads. Entries at the front
|
||||
// get their threads first.
|
||||
nsDeque mPending;
|
||||
};
|
||||
|
||||
StateMachineTracker* StateMachineTracker::mInstance = nsnull;
|
||||
@ -296,7 +313,23 @@ void StateMachineTracker::EnsureGlobalStateMachine()
|
||||
}
|
||||
mStateMachineCount++;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
bool StateMachineTracker::IsQueued(nsBuiltinDecoderStateMachine* aStateMachine)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
PRInt32 size = mPending.GetSize();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
nsBuiltinDecoderStateMachine* m =
|
||||
static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
|
||||
if (m == aStateMachine) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
@ -305,6 +338,7 @@ void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
mStateMachineCount--;
|
||||
if (mStateMachineCount == 0) {
|
||||
LOG(PR_LOG_DEBUG, ("Destroying media state machine thread"));
|
||||
NS_ASSERTION(mPending.GetSize() == 0, "Shouldn't all requests be handled by now?");
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mStateMachineThread);
|
||||
@ -319,16 +353,22 @@ void StateMachineTracker::CleanupGlobalStateMachine()
|
||||
}
|
||||
}
|
||||
|
||||
void StateMachineTracker::NoteDecodeThreadCreated()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
|
||||
void StateMachineTracker::NoteDecodeThreadDestroyed()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
--mDecodeThreadCount;
|
||||
while (mDecodeThreadCount < MAX_DECODE_THREADS && mPending.GetSize() > 0) {
|
||||
nsBuiltinDecoderStateMachine* m =
|
||||
static_cast<nsBuiltinDecoderStateMachine*>(mPending.PopFront());
|
||||
nsresult rv;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mMonitor);
|
||||
rv = m->StartDecodeThread();
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 StateMachineTracker::GetDecodeThreadCount()
|
||||
@ -337,6 +377,45 @@ PRUint32 StateMachineTracker::GetDecodeThreadCount()
|
||||
return mDecodeThreadCount;
|
||||
}
|
||||
|
||||
nsresult StateMachineTracker::CancelCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine) {
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
PRInt32 size = mPending.GetSize();
|
||||
for (PRInt32 i = 0; i < size; ++i) {
|
||||
void* m = static_cast<nsBuiltinDecoderStateMachine*>(mPending.ObjectAt(i));
|
||||
if (m == aStateMachine) {
|
||||
mPending.RemoveObjectAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(!IsQueued(aStateMachine), "State machine should no longer have queued request.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult StateMachineTracker::RequestCreateDecodeThread(nsBuiltinDecoderStateMachine* aStateMachine)
|
||||
{
|
||||
NS_ENSURE_STATE(aStateMachine);
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
if (mPending.GetSize() > 0 || mDecodeThreadCount + 1 >= MAX_DECODE_THREADS) {
|
||||
// If there's already state machines in the queue, or we've exceeded the
|
||||
// limit, append the state machine to the queue of state machines waiting
|
||||
// for a decode thread. This ensures state machines already waiting get
|
||||
// their threads first.
|
||||
mPending.Push(aStateMachine);
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult rv;
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mMonitor);
|
||||
rv = aStateMachine->StartDecodeThread();
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
++mDecodeThreadCount;
|
||||
}
|
||||
NS_ASSERTION(mDecodeThreadCount <= MAX_DECODE_THREADS,
|
||||
"Should keep to thread limit!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
|
||||
nsBuiltinDecoderReader* aReader,
|
||||
bool aRealTime) :
|
||||
@ -367,6 +446,7 @@ nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDe
|
||||
mDispatchedRunEvent(false),
|
||||
mDecodeThreadWaiting(false),
|
||||
mRealTime(aRealTime),
|
||||
mRequestedNewDecodeThread(false),
|
||||
mEventManager(aDecoder)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
|
||||
@ -386,6 +466,10 @@ nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
MOZ_COUNT_DTOR(nsBuiltinDecoderStateMachine);
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Should not have a pending request for a new decode thread");
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Should not have (or flagged) a pending request for a new decode thread");
|
||||
if (mTimer)
|
||||
mTimer->Cancel();
|
||||
mTimer = nsnull;
|
||||
@ -1191,6 +1275,14 @@ void nsBuiltinDecoderStateMachine::StopDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
if (mRequestedNewDecodeThread) {
|
||||
// We've requested that the decode be created, but it hasn't been yet.
|
||||
// Cancel that request.
|
||||
NS_ASSERTION(!mDecodeThread,
|
||||
"Shouldn't have a decode thread until after request processed");
|
||||
StateMachineTracker::Instance().CancelCreateDecodeThread(this);
|
||||
mRequestedNewDecodeThread = false;
|
||||
}
|
||||
mStopDecodeThread = true;
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
if (mDecodeThread) {
|
||||
@ -1203,6 +1295,10 @@ void nsBuiltinDecoderStateMachine::StopDecodeThread()
|
||||
mDecodeThread = nsnull;
|
||||
mDecodeThreadIdle = false;
|
||||
}
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Any pending requests for decode threads must be canceled and unflagged");
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Any pending requests for decode threads must be canceled");
|
||||
}
|
||||
|
||||
void nsBuiltinDecoderStateMachine::StopAudioThread()
|
||||
@ -1221,52 +1317,68 @@ void nsBuiltinDecoderStateMachine::StopAudioThread()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBuiltinDecoderStateMachine::StartDecodeThread()
|
||||
nsBuiltinDecoderStateMachine::ScheduleDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
PRUint32 count = 0;
|
||||
bool created = false;
|
||||
{
|
||||
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
|
||||
count = StateMachineTracker::Instance().GetDecodeThreadCount();
|
||||
}
|
||||
|
||||
|
||||
mStopDecodeThread = false;
|
||||
if ((mDecodeThread && !mDecodeThreadIdle) || mState >= DECODER_STATE_COMPLETED)
|
||||
if (mState >= DECODER_STATE_COMPLETED) {
|
||||
return NS_OK;
|
||||
|
||||
if (!mDecodeThread && count > StateMachineTracker::MAX_DECODE_THREADS) {
|
||||
// Have to run one iteration of the state machine loop to ensure the
|
||||
// shutdown state is processed.
|
||||
ScheduleStateMachine();
|
||||
mState = DECODER_STATE_SHUTDOWN;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mDecodeThread) {
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Have to run one iteration of the state machine loop to ensure the
|
||||
// shutdown state is processed.
|
||||
ScheduleStateMachine();
|
||||
mState = DECODER_STATE_SHUTDOWN;
|
||||
return rv;
|
||||
if (mDecodeThread) {
|
||||
NS_ASSERTION(!mRequestedNewDecodeThread,
|
||||
"Shouldn't have requested new decode thread when we have a decode thread");
|
||||
// We already have a decode thread...
|
||||
if (mDecodeThreadIdle) {
|
||||
// ... and it's not been shutdown yet, wake it up.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
|
||||
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
mDecodeThreadIdle = false;
|
||||
}
|
||||
created = true;
|
||||
return NS_OK;
|
||||
} else if (!mRequestedNewDecodeThread) {
|
||||
// We don't already have a decode thread, request a new one.
|
||||
mRequestedNewDecodeThread = true;
|
||||
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
|
||||
StateMachineTracker::Instance().RequestCreateDecodeThread(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBuiltinDecoderStateMachine::StartDecodeThread()
|
||||
{
|
||||
NS_ASSERTION(StateMachineTracker::Instance().GetDecodeThreadCount() <
|
||||
StateMachineTracker::MAX_DECODE_THREADS,
|
||||
"Should not have reached decode thread limit");
|
||||
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
NS_ASSERTION(!StateMachineTracker::Instance().IsQueued(this),
|
||||
"Should not already have a pending request for a new decode thread.");
|
||||
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
|
||||
NS_ASSERTION(!mDecodeThread, "Should not have decode thread yet");
|
||||
NS_ASSERTION(mRequestedNewDecodeThread, "Should have requested this...");
|
||||
|
||||
mRequestedNewDecodeThread = false;
|
||||
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Give up, report error to media element.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::DecodeError);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
|
||||
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
mDecodeThreadIdle = false;
|
||||
|
||||
if (created) {
|
||||
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
|
||||
StateMachineTracker::Instance().NoteDecodeThreadCreated();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1282,6 +1394,7 @@ nsBuiltinDecoderStateMachine::StartAudioThread()
|
||||
nsnull,
|
||||
MEDIA_THREAD_STACK_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state to SHUTDOWN because failed to create audio thread", mDecoder.get()));
|
||||
mState = DECODER_STATE_SHUTDOWN;
|
||||
return rv;
|
||||
}
|
||||
@ -1639,7 +1752,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
||||
|
||||
case DECODER_STATE_DECODING_METADATA: {
|
||||
// Ensure we have a decode thread to decode metadata.
|
||||
return StartDecodeThread();
|
||||
return ScheduleDecodeThread();
|
||||
}
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
@ -1663,7 +1776,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
||||
|
||||
// We're playing and/or our decode buffers aren't full. Ensure we have
|
||||
// an active decode thread.
|
||||
if (NS_FAILED(StartDecodeThread())) {
|
||||
if (NS_FAILED(ScheduleDecodeThread())) {
|
||||
NS_WARNING("Failed to start media decode thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1728,7 +1841,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
||||
|
||||
case DECODER_STATE_SEEKING: {
|
||||
// Ensure we have a decode thread to perform the seek.
|
||||
return StartDecodeThread();
|
||||
return ScheduleDecodeThread();
|
||||
}
|
||||
|
||||
case DECODER_STATE_COMPLETED: {
|
||||
|
@ -253,6 +253,12 @@ public:
|
||||
// earlier, in which case the request is discarded.
|
||||
nsresult ScheduleStateMachine(PRInt64 aUsecs);
|
||||
|
||||
// Creates and starts a new decode thread. Don't call this directly,
|
||||
// request a new decode thread by calling
|
||||
// StateMachineTracker::RequestCreateDecodeThread().
|
||||
// The decoder monitor must not be held. Called on the state machine thread.
|
||||
nsresult StartDecodeThread();
|
||||
|
||||
// Timer function to implement ScheduleStateMachine(aUsecs).
|
||||
void TimeoutExpired();
|
||||
|
||||
@ -352,7 +358,8 @@ protected:
|
||||
// here. Called on the audio thread.
|
||||
PRUint32 PlayFromAudioQueue(PRUint64 aFrameOffset, PRUint32 aChannels);
|
||||
|
||||
// Stops the decode thread. The decoder monitor must be held with exactly
|
||||
// Stops the decode thread, and if we have a pending request for a new
|
||||
// decode thread it is canceled. The decoder monitor must be held with exactly
|
||||
// one lock count. Called on the state machine thread.
|
||||
void StopDecodeThread();
|
||||
|
||||
@ -360,9 +367,11 @@ protected:
|
||||
// one lock count. Called on the state machine thread.
|
||||
void StopAudioThread();
|
||||
|
||||
// Starts the decode thread. The decoder monitor must be held with exactly
|
||||
// one lock count. Called on the state machine thread.
|
||||
nsresult StartDecodeThread();
|
||||
// Ensures the decode thread is running if it already exists, or requests
|
||||
// a new decode thread be started if there currently is no decode thread.
|
||||
// The decoder monitor must be held with exactly one lock count. Called on
|
||||
// the state machine thread.
|
||||
nsresult ScheduleDecodeThread();
|
||||
|
||||
// Starts the audio thread. The decoder monitor must be held with exactly
|
||||
// one lock count. Called on the state machine thread.
|
||||
@ -625,6 +634,10 @@ protected:
|
||||
|
||||
// True is we are decoding a realtime stream, like a camera stream
|
||||
bool mRealTime;
|
||||
|
||||
// True if we've requested a new decode thread, but it has not yet been
|
||||
// created. Synchronized by the decoder monitor.
|
||||
bool mRequestedNewDecodeThread;
|
||||
|
||||
PRUint32 mBufferingWait;
|
||||
PRInt64 mLowDataThresholdUsecs;
|
||||
|
@ -150,6 +150,7 @@ _TEST_FILES = \
|
||||
test_source_write.html \
|
||||
test_standalone.html \
|
||||
test_timeupdate_small_files.html \
|
||||
test_too_many_elements.html \
|
||||
test_volume.html \
|
||||
test_video_to_canvas.html \
|
||||
use_large_cache.js \
|
||||
|
@ -8,4 +8,4 @@ load 493915-1.html
|
||||
skip-if(Android) load 495794-1.html
|
||||
load 492286-1.xhtml
|
||||
load 576612-1.html
|
||||
load 691096-1.html
|
||||
skip-if(Android) load 691096-1.html # Android sound API can't handle playing large number of sounds at once.
|
||||
|
@ -5,9 +5,9 @@
|
||||
// These are small test files, good for just seeing if something loads. We
|
||||
// really only need one test file per backend here.
|
||||
var gSmallTests = [
|
||||
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
|
||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233 },
|
||||
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
|
||||
{ name:"seek.webm", type:"video/webm", duration:3.966 },
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
@ -299,6 +299,14 @@ function getPlayableVideo(candidates) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPlayableAudio(candidates) {
|
||||
var v = document.createElement("audio");
|
||||
var resources = candidates.filter(function(x){return /^audio/.test(x.type) && v.canPlayType(x.type);});
|
||||
if (resources.length > 0)
|
||||
return resources[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
// Number of tests to run in parallel. Warning: Each media element requires
|
||||
// at least 3 threads (4 on Linux), and on Linux each thread uses 10MB of
|
||||
// virtual address space. Beware!
|
||||
|
68
content/media/test/test_too_many_elements.html
Normal file
68
content/media/test/test_too_many_elements.html
Normal file
@ -0,0 +1,68 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=713381
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 713381</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=713381">Mozilla Bug 713381</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
||||
<p>Received loadeddata event for <span id="result">0</span> <span id="expected"></span>audio elements.</p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 713381 **/
|
||||
|
||||
const num = 500;
|
||||
var loadeddata = 0;
|
||||
|
||||
var result = document.getElementById("result");
|
||||
document.getElementById("expected").innerHTML = " of " + num + " ";
|
||||
|
||||
var finish = function(testNum) {
|
||||
return function() {
|
||||
ok(true, "Received loadeddata event for instance " + testNum );
|
||||
loadeddata++;
|
||||
if (loadeddata == num) {
|
||||
ok(true, "Should receive loadeddata events for all " + num + " elements.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var resource = getPlayableAudio(gSmallTests);
|
||||
|
||||
if (resource == null) {
|
||||
todo(false, "No types supported");
|
||||
} else {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Load the resource, and play it to ensure it's entirely downloaded.
|
||||
// Once it's played through, create a large number of audio elements which
|
||||
// are the same resource. These will share data with the other resource, and
|
||||
// so be really cheap to create.
|
||||
var res = new Audio(resource.name);
|
||||
res.addEventListener("ended",
|
||||
function() {
|
||||
for (var i=0; i<num; ++i) {
|
||||
var a = new Audio(resource.name);
|
||||
a.addEventListener("loadeddata", finish(i), false);
|
||||
}
|
||||
}, false);
|
||||
res.play();
|
||||
}
|
||||
|
||||
setInterval(function() { result.innerHTML = loadeddata; }, 1000);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -66,8 +66,13 @@ DIRS = \
|
||||
interfaces/notification \
|
||||
interfaces/svg \
|
||||
interfaces/smil \
|
||||
$(NULL)
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
DIRS += \
|
||||
interfaces/apps \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
DIRS += \
|
||||
base \
|
||||
|
98
dom/sms/src/ril/SmsDatabaseService.cpp
Normal file
98
dom/sms/src/ril/SmsDatabaseService.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mounir Lamouri <mounir.lamouri@mozilla.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "SmsDatabaseService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace sms {
|
||||
|
||||
NS_IMPL_ISUPPORTS1(SmsDatabaseService, nsISmsDatabaseService)
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsDatabaseService::SaveSentMessage(const nsAString& aReceiver,
|
||||
const nsAString& aBody,
|
||||
PRUint64 aDate, PRInt32* aId)
|
||||
{
|
||||
*aId = -1;
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsDatabaseService::GetMessageMoz(PRInt32 aMessageId, PRInt32 aRequestId,
|
||||
PRUint64 aProcessId)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsDatabaseService::DeleteMessage(PRInt32 aMessageId, PRInt32 aRequestId,
|
||||
PRUint64 aProcessId)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsDatabaseService::CreateMessageList(nsIDOMMozSmsFilter* aFilter,
|
||||
bool aReverse, PRInt32 aRequestId,
|
||||
PRUint64 aProcessId)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsDatabaseService::GetNextMessageInList(PRInt32 aListId, PRInt32 aRequestId,
|
||||
PRUint64 aProcessId)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsDatabaseService::ClearMessageList(PRInt32 aListId)
|
||||
{
|
||||
NS_ERROR("We should not be here!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace sms
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
58
dom/sms/src/ril/SmsDatabaseService.h
Normal file
58
dom/sms/src/ril/SmsDatabaseService.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mounir Lamouri <mounir.lamouri@mozilla.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_dom_sms_SmsDatabaseService_h
|
||||
#define mozilla_dom_sms_SmsDatabaseService_h
|
||||
|
||||
#include "nsISmsDatabaseService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace sms {
|
||||
|
||||
class SmsDatabaseService : public nsISmsDatabaseService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISMSDATABASESERVICE
|
||||
};
|
||||
|
||||
} // namespace sms
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_sms_SmsDatabaseService_h
|
@ -80,7 +80,10 @@ SmsService::GetNumberOfMessagesForText(const nsAString& aText, PRUint16* aResult
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::Send(const nsAString& aNumber, const nsAString& aMessage)
|
||||
SmsService::Send(const nsAString& aNumber,
|
||||
const nsAString& aMessage,
|
||||
PRInt32 aRequestId,
|
||||
PRUint64 aProcessId)
|
||||
{
|
||||
if (!mRIL) {
|
||||
return NS_OK;
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
#include "nsISmsService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsITelephone.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -54,7 +54,7 @@ public:
|
||||
SmsService();
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsITelephone> mRIL;
|
||||
nsCOMPtr<nsIRadioInterfaceLayer> mRIL;
|
||||
};
|
||||
|
||||
} // namespace sms
|
||||
|
@ -79,6 +79,11 @@ LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/android \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/system/b2g \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
EXPORTS += nsGeoPositionIPCSerialiser.h
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
@ -88,6 +88,10 @@
|
||||
#include "AndroidLocationProvider.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "GonkGPSGeolocationProvider.h"
|
||||
#endif
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
@ -577,6 +581,13 @@ nsresult nsGeolocationService::Init()
|
||||
if (provider)
|
||||
mProviders.AppendObject(provider);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
provider = GonkGPSGeolocationProvider::GetSingleton();
|
||||
if (provider)
|
||||
mProviders.AppendObject(provider);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
185
dom/system/b2g/GonkGPSGeolocationProvider.cpp
Normal file
185
dom/system/b2g/GonkGPSGeolocationProvider.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kan-Ru Chen <kchen@mozilla.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <hardware/gps.h>
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsGeoPosition.h"
|
||||
#include "GonkGPSGeolocationProvider.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(GonkGPSGeolocationProvider, nsIGeolocationProvider)
|
||||
|
||||
GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton;
|
||||
|
||||
static void
|
||||
LocationCallback(GpsLocation* location)
|
||||
{
|
||||
nsRefPtr<GonkGPSGeolocationProvider> provider =
|
||||
GonkGPSGeolocationProvider::GetSingleton();
|
||||
nsCOMPtr<nsIGeolocationUpdate> callback = provider->GetLocationCallback();
|
||||
|
||||
if (!callback)
|
||||
return;
|
||||
|
||||
nsRefPtr<nsGeoPosition> somewhere = new nsGeoPosition(location->latitude,
|
||||
location->longitude,
|
||||
location->altitude,
|
||||
location->accuracy,
|
||||
location->accuracy,
|
||||
location->bearing,
|
||||
location->speed,
|
||||
location->timestamp);
|
||||
callback->Update(somewhere);
|
||||
}
|
||||
|
||||
typedef void *(*pthread_func)(void *);
|
||||
|
||||
/** Callback for creating a thread that can call into the JS codes.
|
||||
*/
|
||||
static pthread_t
|
||||
CreateThreadCallback(const char* name, void (*start)(void *), void* arg)
|
||||
{
|
||||
pthread_t thread;
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
/* Unfortunately pthread_create and the callback disagreed on what
|
||||
* start function should return.
|
||||
*/
|
||||
pthread_create(&thread, &attr, reinterpret_cast<pthread_func>(start), arg);
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
static GpsCallbacks gCallbacks = {
|
||||
sizeof(GpsCallbacks),
|
||||
LocationCallback,
|
||||
NULL, /* StatusCallback */
|
||||
NULL, /* SvStatusCallback */
|
||||
NULL, /* NmeaCallback */
|
||||
NULL, /* SetCapabilitiesCallback */
|
||||
NULL, /* AcquireWakelockCallback */
|
||||
NULL, /* ReleaseWakelockCallback */
|
||||
CreateThreadCallback,
|
||||
};
|
||||
|
||||
GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
|
||||
: mStarted(false)
|
||||
{
|
||||
mGpsInterface = GetGPSInterface();
|
||||
}
|
||||
|
||||
GonkGPSGeolocationProvider::~GonkGPSGeolocationProvider()
|
||||
{
|
||||
Shutdown();
|
||||
sSingleton = NULL;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<GonkGPSGeolocationProvider>
|
||||
GonkGPSGeolocationProvider::GetSingleton()
|
||||
{
|
||||
if (!sSingleton)
|
||||
sSingleton = new GonkGPSGeolocationProvider();
|
||||
|
||||
NS_ADDREF(sSingleton);
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIGeolocationUpdate>
|
||||
GonkGPSGeolocationProvider::GetLocationCallback()
|
||||
{
|
||||
nsCOMPtr<nsIGeolocationUpdate> callback = mLocationCallback;
|
||||
return callback.forget();
|
||||
}
|
||||
|
||||
const GpsInterface*
|
||||
GonkGPSGeolocationProvider::GetGPSInterface()
|
||||
{
|
||||
hw_module_t* module;
|
||||
|
||||
if (hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module))
|
||||
return NULL;
|
||||
|
||||
hw_device_t* device;
|
||||
if (module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device))
|
||||
return NULL;
|
||||
|
||||
gps_device_t* gps_device = (gps_device_t *)device;
|
||||
return gps_device->get_gps_interface(gps_device);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Startup()
|
||||
{
|
||||
if (mStarted)
|
||||
return NS_OK;
|
||||
|
||||
NS_ENSURE_TRUE(mGpsInterface, NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 update = Preferences::GetInt("geo.default.update", 1000);
|
||||
|
||||
mGpsInterface->init(&gCallbacks);
|
||||
mGpsInterface->start();
|
||||
mGpsInterface->set_position_mode(GPS_POSITION_MODE_STANDALONE,
|
||||
GPS_POSITION_RECURRENCE_PERIODIC,
|
||||
update, 0, 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Watch(nsIGeolocationUpdate* aCallback)
|
||||
{
|
||||
mLocationCallback = aCallback;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GonkGPSGeolocationProvider::Shutdown()
|
||||
{
|
||||
if (!mStarted)
|
||||
return NS_OK;
|
||||
|
||||
mGpsInterface->stop();
|
||||
mGpsInterface->cleanup();
|
||||
|
||||
return NS_OK;
|
||||
}
|
70
dom/system/b2g/GonkGPSGeolocationProvider.h
Normal file
70
dom/system/b2g/GonkGPSGeolocationProvider.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kan-Ru Chen <kchen@mozilla.com> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef GonkGPSGeolocationProvider_h
|
||||
#define GonkGPSGeolocationProvider_h
|
||||
|
||||
#include <hardware/gps.h> // for GpsInterface
|
||||
#include "nsIGeolocationProvider.h"
|
||||
|
||||
class GonkGPSGeolocationProvider : public nsIGeolocationProvider
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIGEOLOCATIONPROVIDER
|
||||
|
||||
static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
|
||||
|
||||
already_AddRefed<nsIGeolocationUpdate> GetLocationCallback();
|
||||
|
||||
private:
|
||||
|
||||
/* Client should use GetSingleton() to get the provider instance. */
|
||||
GonkGPSGeolocationProvider();
|
||||
GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
|
||||
GonkGPSGeolocationProvider & operator = (const GonkGPSGeolocationProvider &);
|
||||
~GonkGPSGeolocationProvider();
|
||||
|
||||
const GpsInterface* GetGPSInterface();
|
||||
|
||||
static GonkGPSGeolocationProvider* sSingleton;
|
||||
|
||||
bool mStarted;
|
||||
const GpsInterface* mGpsInterface;
|
||||
nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
|
||||
};
|
||||
|
||||
#endif /* GonkGPSGeolocationProvider_h */
|
@ -55,19 +55,34 @@ CPPSRCS = \
|
||||
$(NULL)
|
||||
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
CPPSRCS += AudioManager.cpp
|
||||
CPPSRCS += \
|
||||
AudioManager.cpp \
|
||||
GonkGPSGeolocationProvider.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIAudioManager.idl \
|
||||
nsIRadioInterfaceLayer.idl \
|
||||
nsIWorkerHolder.idl \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(topsrcdir)/dom/src/geolocation \
|
||||
-I$(topsrcdir)/dom/telephony \
|
||||
-I$(topsrcdir)/dom/wifi \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
RadioInterfaceLayer.manifest \
|
||||
RadioInterfaceLayer.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
ril_consts.js \
|
||||
ril_worker.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -14,13 +14,14 @@
|
||||
* The Original Code is Telephony.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
* Sinker Li <thinker@codemud.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -48,13 +49,13 @@ Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
||||
|
||||
const DEBUG = true; // set to false to suppress debug messages
|
||||
|
||||
const TELEPHONYWORKER_CID =
|
||||
const RADIOINTERFACELAYER_CID =
|
||||
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
|
||||
const DATACALLINFO_CID =
|
||||
Components.ID("{ef474cd9-94f7-4c05-a31b-29b9de8a10d2}");
|
||||
|
||||
const nsIAudioManager = Ci.nsIAudioManager;
|
||||
const nsITelephone = Ci.nsITelephone;
|
||||
const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
|
||||
|
||||
const kSmsReceivedObserverTopic = "sms-received";
|
||||
const DOM_SMS_DELIVERY_RECEIVED = "received";
|
||||
@ -66,17 +67,17 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
|
||||
function convertRILCallState(state) {
|
||||
switch (state) {
|
||||
case RIL.CALL_STATE_ACTIVE:
|
||||
return nsITelephone.CALL_STATE_CONNECTED;
|
||||
return nsIRadioInterfaceLayer.CALL_STATE_CONNECTED;
|
||||
case RIL.CALL_STATE_HOLDING:
|
||||
return nsITelephone.CALL_STATE_HELD;
|
||||
return nsIRadioInterfaceLayer.CALL_STATE_HELD;
|
||||
case RIL.CALL_STATE_DIALING:
|
||||
return nsITelephone.CALL_STATE_DIALING;
|
||||
return nsIRadioInterfaceLayer.CALL_STATE_DIALING;
|
||||
case RIL.CALL_STATE_ALERTING:
|
||||
return nsITelephone.CALL_STATE_RINGING;
|
||||
return nsIRadioInterfaceLayer.CALL_STATE_RINGING;
|
||||
case RIL.CALL_STATE_INCOMING:
|
||||
return nsITelephone.CALL_STATE_INCOMING;
|
||||
return nsIRadioInterfaceLayer.CALL_STATE_INCOMING;
|
||||
case RIL.CALL_STATE_WAITING:
|
||||
return nsITelephone.CALL_STATE_HELD; // XXX This may not be right...
|
||||
return nsIRadioInterfaceLayer.CALL_STATE_HELD; // XXX This may not be right...
|
||||
default:
|
||||
throw new Error("Unknown rilCallState: " + state);
|
||||
}
|
||||
@ -126,7 +127,7 @@ DataCallInfo.protoptype = {
|
||||
};
|
||||
|
||||
|
||||
function nsTelephonyWorker() {
|
||||
function RadioInterfaceLayer() {
|
||||
this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
|
||||
this.worker.onerror = this.onerror.bind(this);
|
||||
this.worker.onmessage = this.onmessage.bind(this);
|
||||
@ -138,16 +139,16 @@ function nsTelephonyWorker() {
|
||||
cardState: null
|
||||
};
|
||||
}
|
||||
nsTelephonyWorker.prototype = {
|
||||
RadioInterfaceLayer.prototype = {
|
||||
|
||||
classID: TELEPHONYWORKER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: TELEPHONYWORKER_CID,
|
||||
classDescription: "Telephone",
|
||||
classID: RADIOINTERFACELAYER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
|
||||
classDescription: "RadioInterfaceLayer",
|
||||
interfaces: [Ci.nsIWorkerHolder,
|
||||
Ci.nsITelephone]}),
|
||||
Ci.nsIRadioInterfaceLayer]}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
|
||||
Ci.nsITelephone]),
|
||||
Ci.nsIRadioInterfaceLayer]),
|
||||
|
||||
onerror: function onerror(event) {
|
||||
debug("Got an error: " + event.filename + ":" +
|
||||
@ -219,12 +220,12 @@ nsTelephonyWorker.prototype = {
|
||||
return;
|
||||
}
|
||||
switch (this._activeCall.state) {
|
||||
case nsITelephone.CALL_STATE_INCOMING:
|
||||
case nsIRadioInterfaceLayer.CALL_STATE_INCOMING:
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
|
||||
debug("Incoming call, put audio system into PHONE_STATE_RINGTONE.");
|
||||
break;
|
||||
case nsITelephone.CALL_STATE_DIALING: // Fall through...
|
||||
case nsITelephone.CALL_STATE_CONNECTED:
|
||||
case nsIRadioInterfaceLayer.CALL_STATE_DIALING: // Fall through...
|
||||
case nsIRadioInterfaceLayer.CALL_STATE_CONNECTED:
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
|
||||
nsIAudioManager.FORCE_NONE);
|
||||
@ -240,7 +241,7 @@ nsTelephonyWorker.prototype = {
|
||||
handleCallStateChange: function handleCallStateChange(call) {
|
||||
debug("handleCallStateChange: " + JSON.stringify(call));
|
||||
call.state = convertRILCallState(call.state);
|
||||
if (call.state == nsITelephone.CALL_STATE_CONNECTED) {
|
||||
if (call.state == nsIRadioInterfaceLayer.CALL_STATE_CONNECTED) {
|
||||
// This is now the active call.
|
||||
this._activeCall = call;
|
||||
}
|
||||
@ -259,7 +260,8 @@ nsTelephonyWorker.prototype = {
|
||||
}
|
||||
this.updateCallAudioState();
|
||||
this._deliverCallback("callStateChanged",
|
||||
[call.callIndex, nsITelephone.CALL_STATE_DISCONNECTED,
|
||||
[call.callIndex,
|
||||
nsIRadioInterfaceLayer.CALL_STATE_DISCONNECTED,
|
||||
call.number]);
|
||||
},
|
||||
|
||||
@ -327,7 +329,7 @@ nsTelephonyWorker.prototype = {
|
||||
|
||||
worker: null,
|
||||
|
||||
// nsITelephone
|
||||
// nsIRadioInterfaceLayer
|
||||
|
||||
currentState: null,
|
||||
|
||||
@ -540,12 +542,12 @@ nsTelephonyWorker.prototype = {
|
||||
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([nsTelephonyWorker]);
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([RadioInterfaceLayer]);
|
||||
|
||||
let debug;
|
||||
if (DEBUG) {
|
||||
debug = function (s) {
|
||||
dump("-*- TelephonyWorker component: " + s + "\n");
|
||||
dump("-*- RadioInterfaceLayer: " + s + "\n");
|
||||
};
|
||||
} else {
|
||||
debug = function (s) {};
|
1
dom/system/b2g/RadioInterfaceLayer.manifest
Normal file
1
dom/system/b2g/RadioInterfaceLayer.manifest
Normal file
@ -0,0 +1 @@
|
||||
component {2d831c8d-6017-435b-a80c-e5d422810cea} RadioInterfaceLayer.js
|
@ -41,7 +41,7 @@
|
||||
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsITelephone.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
#include "nsIWifi.h"
|
||||
#include "nsIWorkerHolder.h"
|
||||
#include "nsIXPConnect.h"
|
||||
@ -51,8 +51,8 @@
|
||||
#include "mozilla/ipc/Ril.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsTelephonyWorker.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsRadioInterfaceLayer.h"
|
||||
#include "nsWifiWorker.h"
|
||||
|
||||
USING_TELEPHONY_NAMESPACE
|
||||
@ -61,7 +61,7 @@ using namespace mozilla::ipc;
|
||||
|
||||
namespace {
|
||||
|
||||
NS_DEFINE_CID(kTelephonyWorkerCID, NS_TELEPHONYWORKER_CID);
|
||||
NS_DEFINE_CID(kRadioInterfaceLayerCID, NS_RADIOINTERFACELAYER_CID);
|
||||
NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
|
||||
|
||||
// Doesn't carry a reference, we're owned by services.
|
||||
@ -224,7 +224,7 @@ SystemWorkerManager::Init()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = InitTelephone(cx);
|
||||
rv = InitRIL(cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = InitWifi(cx);
|
||||
@ -252,7 +252,7 @@ SystemWorkerManager::Shutdown()
|
||||
|
||||
StopRil();
|
||||
|
||||
mTelephoneWorker = nsnull;
|
||||
mRILWorker = nsnull;
|
||||
mWifiWorker = nsnull;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
@ -295,9 +295,9 @@ SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsITelephone))) {
|
||||
return CallQueryInterface(mTelephoneWorker,
|
||||
reinterpret_cast<nsITelephone**>(aResult));
|
||||
if (aIID.Equals(NS_GET_IID(nsIRadioInterfaceLayer))) {
|
||||
return CallQueryInterface(mRILWorker,
|
||||
reinterpret_cast<nsIRadioInterfaceLayer**>(aResult));
|
||||
}
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsIWifi))) {
|
||||
@ -310,12 +310,12 @@ SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
|
||||
}
|
||||
|
||||
nsresult
|
||||
SystemWorkerManager::InitTelephone(JSContext *cx)
|
||||
SystemWorkerManager::InitRIL(JSContext *cx)
|
||||
{
|
||||
// We're keeping as much of this implementation as possible in JS, so the real
|
||||
// worker lives in nsTelephonyWorker.js. All we do here is hold it alive and
|
||||
// worker lives in RadioInterfaceLayer.js. All we do here is hold it alive and
|
||||
// hook it up to the RIL thread.
|
||||
nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kTelephonyWorkerCID);
|
||||
nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kRadioInterfaceLayerCID);
|
||||
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
|
||||
|
||||
jsval workerval;
|
||||
@ -345,7 +345,7 @@ SystemWorkerManager::InitTelephone(JSContext *cx)
|
||||
mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
|
||||
StartRil(receiver);
|
||||
|
||||
mTelephoneWorker = worker;
|
||||
mRILWorker = worker;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -70,10 +70,10 @@ private:
|
||||
SystemWorkerManager();
|
||||
~SystemWorkerManager();
|
||||
|
||||
nsresult InitTelephone(JSContext *cx);
|
||||
nsresult InitRIL(JSContext *cx);
|
||||
nsresult InitWifi(JSContext *cx);
|
||||
|
||||
nsCOMPtr<nsIWorkerHolder> mTelephoneWorker;
|
||||
nsCOMPtr<nsIWorkerHolder> mRILWorker;
|
||||
nsCOMPtr<nsIWorkerHolder> mWifiWorker;
|
||||
|
||||
bool mShutdown;
|
||||
|
@ -19,7 +19,9 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
* Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
* Ben Turner <bent.mozilla@gmail.com>
|
||||
* Sinker Li <thinker@codemud.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -37,48 +39,85 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(9b7e3a01-9c45-4af3-81bb-1bf08a842226)]
|
||||
interface nsITelephoneCallback : nsISupports
|
||||
[scriptable, uuid(03eafd60-d138-4f09-81b4-90cd4996b3c7)]
|
||||
interface nsIRILTelephonyCallback : nsISupports
|
||||
{
|
||||
// 'callState' uses the CALL_STATE values from nsITelephone.
|
||||
/**
|
||||
* Notified when a telephony call changes state.
|
||||
*
|
||||
* @param callIndex
|
||||
* Call identifier assigned by the RIL.
|
||||
* @param callState
|
||||
* One of the nsIRadioInterfaceLayer::CALL_STATE_* values.
|
||||
* @param number
|
||||
* Number of the other party.
|
||||
*/
|
||||
void callStateChanged(in unsigned long callIndex,
|
||||
in unsigned short callState,
|
||||
in AString number);
|
||||
|
||||
// 'callState' uses the CALL_STATE values from nsITelephone. Return true to
|
||||
// continue enumeration or false to cancel.
|
||||
/**
|
||||
* Called when nsIRadioInterfaceLayer is asked to enumerate the current
|
||||
* telephony call state (nsIRadioInterfaceLayer::enumerateCalls). This is
|
||||
* called once per call that is currently managed by the RIL.
|
||||
*
|
||||
* @param callIndex
|
||||
* Call identifier assigned by the RIL.
|
||||
* @param callState
|
||||
* One of the nsIRadioInterfaceLayer::CALL_STATE_* values.
|
||||
* @param number
|
||||
* Number of the other party.
|
||||
* @param isActive
|
||||
* Indicates whether this call is the active one.
|
||||
*
|
||||
* @return true to continue enumeration or false to cancel.
|
||||
*/
|
||||
boolean enumerateCallState(in unsigned long callIndex,
|
||||
in unsigned short callState,
|
||||
in AString number,
|
||||
in boolean isActive);
|
||||
};
|
||||
|
||||
[scriptable, uuid(8399fddd-471c-41ac-8f35-99f7dbb738ec)]
|
||||
interface nsIDataCallInfo : nsISupports
|
||||
[scriptable, uuid(66a55943-e63b-4731-aece-9c04bfc14019)]
|
||||
interface nsIRILDataCallInfo : nsISupports
|
||||
{
|
||||
readonly attribute unsigned long callState;
|
||||
readonly attribute AString cid;
|
||||
readonly attribute AString apn;
|
||||
};
|
||||
|
||||
[scriptable, uuid(36cc4b89-0338-4ff7-a3c2-d78e60f2ea98)]
|
||||
interface nsIPhoneDataCallCallback : nsISupports
|
||||
[scriptable, uuid(cea91bcb-3cfb-42bb-8638-dae89e8870fc)]
|
||||
interface nsIRILDataCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
* This method is called when the state of a data call is changed.
|
||||
* Notified when a data call changes state.
|
||||
*
|
||||
* @param dataState use DATACALL_STATE_* values from nsITelephone.
|
||||
* @param cid
|
||||
* The CID of the data call.
|
||||
* @param interfaceName
|
||||
* Name of the associated network interface.
|
||||
* @param dataState
|
||||
* One of the nsIRadioInterfaceLayer::DATACALL_STATE_* values.
|
||||
*/
|
||||
void dataCallStateChanged(in AString cid,
|
||||
in AString interfaceName,
|
||||
in unsigned short callState);
|
||||
|
||||
void receiveDataCallList([array,size_is(aLength)] in nsIDataCallInfo aDataCalls,
|
||||
in unsigned long aLength);
|
||||
/**
|
||||
* Called when nsIRadioInterfaceLayer is asked to enumerate the current
|
||||
* data call state.
|
||||
*
|
||||
* @param datacalls
|
||||
* Array of nsIRILDataCallInfo objects.
|
||||
* @param length
|
||||
* Lenght of the aforementioned array.
|
||||
*/
|
||||
void receiveDataCallList([array,size_is(length)] in nsIRILDataCallInfo dataCalls,
|
||||
in unsigned long length);
|
||||
};
|
||||
|
||||
[scriptable, uuid(78ed0beb-d6ad-42f8-929a-8d003285784f)]
|
||||
interface nsITelephone : nsISupports
|
||||
[scriptable, uuid(9b7e3a01-9c45-4af3-81bb-1bf08a842226)]
|
||||
interface nsIRadioInterfaceLayer : nsISupports
|
||||
{
|
||||
const unsigned short CALL_STATE_UNKNOWN = 0;
|
||||
const unsigned short CALL_STATE_DIALING = 1;
|
||||
@ -102,14 +141,14 @@ interface nsITelephone : nsISupports
|
||||
|
||||
readonly attribute jsval currentState;
|
||||
|
||||
void registerCallback(in nsITelephoneCallback callback);
|
||||
void unregisterCallback(in nsITelephoneCallback callback);
|
||||
void registerCallback(in nsIRILTelephonyCallback callback);
|
||||
void unregisterCallback(in nsIRILTelephonyCallback callback);
|
||||
|
||||
/**
|
||||
* Will continue calling callback.enumerateCallState until the callback
|
||||
* returns false.
|
||||
*/
|
||||
void enumerateCalls(in nsITelephoneCallback callback);
|
||||
void enumerateCalls(in nsIRILTelephonyCallback callback);
|
||||
|
||||
/**
|
||||
* Functionality for making and managing phone calls.
|
||||
@ -126,7 +165,9 @@ interface nsITelephone : nsISupports
|
||||
attribute bool microphoneMuted;
|
||||
attribute bool speakerEnabled;
|
||||
|
||||
// PDP APIs
|
||||
/**
|
||||
* PDP APIs
|
||||
*/
|
||||
void setupDataCall(in long radioTech,
|
||||
in DOMString apn,
|
||||
in DOMString user,
|
||||
@ -137,8 +178,8 @@ interface nsITelephone : nsISupports
|
||||
in DOMString reason);
|
||||
void getDataCallList();
|
||||
|
||||
void registerDataCallCallback(in nsIPhoneDataCallCallback callback);
|
||||
void unregisterDataCallCallback(in nsIPhoneDataCallCallback callback);
|
||||
void registerDataCallCallback(in nsIRILDataCallback callback);
|
||||
void unregisterDataCallCallback(in nsIRILDataCallback callback);
|
||||
|
||||
/**
|
||||
* SMS-related functionality.
|
@ -35,7 +35,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// This must always match the CID given in nsTelephonyWorker.manifest!
|
||||
#define NS_TELEPHONYWORKER_CID \
|
||||
// This must always match the CID given in RadioInterfaceLayer.manifest!
|
||||
#define NS_RADIOINTERFACELAYER_CID \
|
||||
{ 0x2d831c8d, 0x6017, 0x435b, \
|
||||
{ 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } }
|
@ -61,18 +61,12 @@ XPIDLSRCS = \
|
||||
nsIDOMTelephony.idl \
|
||||
nsIDOMTelephonyCall.idl \
|
||||
nsIDOMCallEvent.idl \
|
||||
nsITelephone.idl \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
nsTelephonyWorker.manifest \
|
||||
nsTelephonyWorker.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
ril_consts.js \
|
||||
ril_worker.js \
|
||||
$(NULL)
|
||||
#LOCAL_INCLUDES = \
|
||||
# -I$(topsrcdir)/dom/base \
|
||||
# -I$(topsrcdir)/dom/system/b2g \
|
||||
# -I$(topsrcdir)/content/events/src \
|
||||
# $(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -112,8 +112,8 @@ nsTArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
|
||||
|
||||
Telephony::~Telephony()
|
||||
{
|
||||
if (mTelephone && mTelephoneCallback) {
|
||||
mTelephone->UnregisterCallback(mTelephoneCallback);
|
||||
if (mRIL && mRILTelephonyCallback) {
|
||||
mRIL->UnregisterCallback(mRILTelephonyCallback);
|
||||
}
|
||||
|
||||
if (mRooted) {
|
||||
@ -123,10 +123,10 @@ Telephony::~Telephony()
|
||||
|
||||
// static
|
||||
already_AddRefed<Telephony>
|
||||
Telephony::Create(nsPIDOMWindow* aOwner, nsITelephone* aTelephone)
|
||||
Telephony::Create(nsPIDOMWindow* aOwner, nsIRadioInterfaceLayer* aRIL)
|
||||
{
|
||||
NS_ASSERTION(aOwner, "Null owner!");
|
||||
NS_ASSERTION(aTelephone, "Null telephone!");
|
||||
NS_ASSERTION(aRIL, "Null RIL!");
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
|
||||
NS_ENSURE_TRUE(sgo, nsnull);
|
||||
@ -138,13 +138,13 @@ Telephony::Create(nsPIDOMWindow* aOwner, nsITelephone* aTelephone)
|
||||
|
||||
telephony->mOwner = aOwner;
|
||||
telephony->mScriptContext.swap(scriptContext);
|
||||
telephony->mTelephone = aTelephone;
|
||||
telephony->mTelephoneCallback = new TelephoneCallback(telephony);
|
||||
telephony->mRIL = aRIL;
|
||||
telephony->mRILTelephonyCallback = new RILTelephonyCallback(telephony);
|
||||
|
||||
nsresult rv = aTelephone->EnumerateCalls(telephony->mTelephoneCallback);
|
||||
nsresult rv = aRIL->EnumerateCalls(telephony->mRILTelephonyCallback);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
rv = aTelephone->RegisterCallback(telephony->mTelephoneCallback);
|
||||
rv = aRIL->RegisterCallback(telephony->mRILTelephonyCallback);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
return telephony.forget();
|
||||
@ -195,7 +195,7 @@ NS_IMPL_RELEASE_INHERITED(Telephony, nsDOMEventTargetWrapperCache)
|
||||
|
||||
DOMCI_DATA(Telephony, Telephony)
|
||||
|
||||
NS_IMPL_ISUPPORTS1(Telephony::TelephoneCallback, nsITelephoneCallback)
|
||||
NS_IMPL_ISUPPORTS1(Telephony::RILTelephonyCallback, nsIRILTelephonyCallback)
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
|
||||
@ -205,7 +205,7 @@ Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
|
||||
for (PRUint32 index = 0; index < mCalls.Length(); index++) {
|
||||
const nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
|
||||
if (tempCall->IsOutgoing() &&
|
||||
tempCall->CallState() < nsITelephone::CALL_STATE_CONNECTED) {
|
||||
tempCall->CallState() < nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) {
|
||||
// One call has been dialed already and we only support one outgoing call
|
||||
// at a time.
|
||||
NS_WARNING("Only permitted to dial one call at a time!");
|
||||
@ -213,11 +213,11 @@ Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = mTelephone->Dial(aNumber);
|
||||
nsresult rv = mRIL->Dial(aNumber);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<TelephonyCall> call =
|
||||
TelephonyCall::Create(this, aNumber, nsITelephone::CALL_STATE_DIALING);
|
||||
TelephonyCall::Create(this, aNumber, nsIRadioInterfaceLayer::CALL_STATE_DIALING);
|
||||
NS_ASSERTION(call, "This should never fail!");
|
||||
|
||||
NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
|
||||
@ -229,7 +229,7 @@ Telephony::Dial(const nsAString& aNumber, nsIDOMTelephonyCall** aResult)
|
||||
NS_IMETHODIMP
|
||||
Telephony::GetMuted(bool* aMuted)
|
||||
{
|
||||
nsresult rv = mTelephone->GetMicrophoneMuted(aMuted);
|
||||
nsresult rv = mRIL->GetMicrophoneMuted(aMuted);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -238,7 +238,7 @@ Telephony::GetMuted(bool* aMuted)
|
||||
NS_IMETHODIMP
|
||||
Telephony::SetMuted(bool aMuted)
|
||||
{
|
||||
nsresult rv = mTelephone->SetMicrophoneMuted(aMuted);
|
||||
nsresult rv = mRIL->SetMicrophoneMuted(aMuted);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -247,7 +247,7 @@ Telephony::SetMuted(bool aMuted)
|
||||
NS_IMETHODIMP
|
||||
Telephony::GetSpeakerEnabled(bool* aSpeakerEnabled)
|
||||
{
|
||||
nsresult rv = mTelephone->GetSpeakerEnabled(aSpeakerEnabled);
|
||||
nsresult rv = mRIL->GetSpeakerEnabled(aSpeakerEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -256,7 +256,7 @@ Telephony::GetSpeakerEnabled(bool* aSpeakerEnabled)
|
||||
NS_IMETHODIMP
|
||||
Telephony::SetSpeakerEnabled(bool aSpeakerEnabled)
|
||||
{
|
||||
nsresult rv = mTelephone->SetSpeakerEnabled(aSpeakerEnabled);
|
||||
nsresult rv = mRIL->SetSpeakerEnabled(aSpeakerEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -339,7 +339,7 @@ Telephony::StartTone(const nsAString& aDTMFChar)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv = mTelephone->StartTone(aDTMFChar);
|
||||
nsresult rv = mRIL->StartTone(aDTMFChar);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -348,7 +348,7 @@ Telephony::StartTone(const nsAString& aDTMFChar)
|
||||
NS_IMETHODIMP
|
||||
Telephony::StopTone()
|
||||
{
|
||||
nsresult rv = mTelephone->StopTone();
|
||||
nsresult rv = mRIL->StopTone();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -378,7 +378,7 @@ Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
|
||||
nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
|
||||
if (tempCall->CallIndex() == kOutgoingPlaceholderCallIndex) {
|
||||
NS_ASSERTION(!outgoingCall, "More than one outgoing call not supported!");
|
||||
NS_ASSERTION(tempCall->CallState() == nsITelephone::CALL_STATE_DIALING,
|
||||
NS_ASSERTION(tempCall->CallState() == nsIRadioInterfaceLayer::CALL_STATE_DIALING,
|
||||
"Something really wrong here!");
|
||||
// Stash this for later, we may need it if aCallIndex doesn't match one of
|
||||
// our other calls.
|
||||
@ -395,7 +395,7 @@ Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
|
||||
// an outgoing call then we must be seeing a status update for our outgoing
|
||||
// call.
|
||||
if (!modifiedCall &&
|
||||
aCallState != nsITelephone::CALL_STATE_INCOMING &&
|
||||
aCallState != nsIRadioInterfaceLayer::CALL_STATE_INCOMING &&
|
||||
outgoingCall) {
|
||||
outgoingCall->UpdateCallIndex(aCallIndex);
|
||||
modifiedCall.swap(outgoingCall);
|
||||
@ -406,7 +406,7 @@ Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
|
||||
modifiedCall->ChangeState(aCallState);
|
||||
|
||||
// See if this should replace our current active call.
|
||||
if (aCallState == nsITelephone::CALL_STATE_CONNECTED) {
|
||||
if (aCallState == nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) {
|
||||
SwitchActiveCall(modifiedCall);
|
||||
}
|
||||
|
||||
@ -414,7 +414,7 @@ Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
|
||||
}
|
||||
|
||||
// Didn't know anything about this call before now, must be incoming.
|
||||
NS_ASSERTION(aCallState == nsITelephone::CALL_STATE_INCOMING,
|
||||
NS_ASSERTION(aCallState == nsIRadioInterfaceLayer::CALL_STATE_INCOMING,
|
||||
"Serious logic problem here!");
|
||||
|
||||
nsRefPtr<TelephonyCall> call =
|
||||
@ -511,10 +511,10 @@ NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony)
|
||||
nsIInterfaceRequestor* ireq = SystemWorkerManager::GetInterfaceRequestor();
|
||||
NS_ENSURE_TRUE(ireq, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsITelephone> telephone = do_GetInterface(ireq);
|
||||
NS_ENSURE_TRUE(telephone, NS_ERROR_UNEXPECTED);
|
||||
nsCOMPtr<nsIRadioInterfaceLayer> ril = do_GetInterface(ireq);
|
||||
NS_ENSURE_TRUE(ril, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsRefPtr<Telephony> telephony = Telephony::Create(innerWindow, telephone);
|
||||
nsRefPtr<Telephony> telephony = Telephony::Create(innerWindow, ril);
|
||||
NS_ENSURE_TRUE(telephony, NS_ERROR_UNEXPECTED);
|
||||
|
||||
telephony.forget(aTelephony);
|
||||
|
@ -44,7 +44,7 @@
|
||||
|
||||
#include "nsIDOMTelephony.h"
|
||||
#include "nsIDOMTelephonyCall.h"
|
||||
#include "nsITelephone.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsPIDOMWindow;
|
||||
@ -54,8 +54,8 @@ BEGIN_TELEPHONY_NAMESPACE
|
||||
class Telephony : public nsDOMEventTargetWrapperCache,
|
||||
public nsIDOMTelephony
|
||||
{
|
||||
nsCOMPtr<nsITelephone> mTelephone;
|
||||
nsCOMPtr<nsITelephoneCallback> mTelephoneCallback;
|
||||
nsCOMPtr<nsIRadioInterfaceLayer> mRIL;
|
||||
nsCOMPtr<nsIRILTelephonyCallback> mRILTelephonyCallback;
|
||||
|
||||
NS_DECL_EVENT_HANDLER(incoming);
|
||||
|
||||
@ -71,14 +71,14 @@ class Telephony : public nsDOMEventTargetWrapperCache,
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMTELEPHONY
|
||||
NS_DECL_NSITELEPHONECALLBACK
|
||||
NS_DECL_NSIRILTELEPHONYCALLBACK
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetWrapperCache::)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
|
||||
Telephony,
|
||||
nsDOMEventTargetWrapperCache)
|
||||
|
||||
static already_AddRefed<Telephony>
|
||||
Create(nsPIDOMWindow* aOwner, nsITelephone* aTelephone);
|
||||
Create(nsPIDOMWindow* aOwner, nsIRadioInterfaceLayer* aRIL);
|
||||
|
||||
nsIDOMEventTarget*
|
||||
ToIDOMEventTarget() const
|
||||
@ -109,10 +109,10 @@ public:
|
||||
mCallsArray = nsnull;
|
||||
}
|
||||
|
||||
nsITelephone*
|
||||
Telephone() const
|
||||
nsIRadioInterfaceLayer*
|
||||
RIL() const
|
||||
{
|
||||
return mTelephone;
|
||||
return mRIL;
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
@ -137,15 +137,15 @@ private:
|
||||
void
|
||||
SwitchActiveCall(TelephonyCall* aCall);
|
||||
|
||||
class TelephoneCallback : public nsITelephoneCallback
|
||||
class RILTelephonyCallback : public nsIRILTelephonyCallback
|
||||
{
|
||||
Telephony* mTelephony;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSITELEPHONECALLBACK(mTelephony->)
|
||||
NS_FORWARD_NSIRILTELEPHONYCALLBACK(mTelephony->)
|
||||
|
||||
TelephoneCallback(Telephony* aTelephony)
|
||||
RILTelephonyCallback(Telephony* aTelephony)
|
||||
: mTelephony(aTelephony)
|
||||
{
|
||||
NS_ASSERTION(mTelephony, "Null pointer!");
|
||||
|
@ -75,37 +75,37 @@ TelephonyCall::ChangeStateInternal(PRUint16 aCallState, bool aFireEvents)
|
||||
|
||||
nsString stateString;
|
||||
switch (aCallState) {
|
||||
case nsITelephone::CALL_STATE_DIALING:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
|
||||
stateString.AssignLiteral("dialing");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_RINGING:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_RINGING:
|
||||
stateString.AssignLiteral("ringing");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_BUSY:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_BUSY:
|
||||
stateString.AssignLiteral("busy");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_CONNECTING:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_CONNECTING:
|
||||
stateString.AssignLiteral("connecting");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_CONNECTED:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
|
||||
stateString.AssignLiteral("connected");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_HOLDING:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_HOLDING:
|
||||
stateString.AssignLiteral("holding");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_HELD:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_HELD:
|
||||
stateString.AssignLiteral("held");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_RESUMING:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_RESUMING:
|
||||
stateString.AssignLiteral("resuming");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_DISCONNECTING:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTING:
|
||||
stateString.AssignLiteral("disconnecting");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_DISCONNECTED:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED:
|
||||
stateString.AssignLiteral("disconnected");
|
||||
break;
|
||||
case nsITelephone::CALL_STATE_INCOMING:
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
|
||||
stateString.AssignLiteral("incoming");
|
||||
break;
|
||||
default:
|
||||
@ -115,11 +115,11 @@ TelephonyCall::ChangeStateInternal(PRUint16 aCallState, bool aFireEvents)
|
||||
mState = stateString;
|
||||
mCallState = aCallState;
|
||||
|
||||
if (aCallState == nsITelephone::CALL_STATE_DIALING) {
|
||||
if (aCallState == nsIRadioInterfaceLayer::CALL_STATE_DIALING) {
|
||||
mOutgoing = true;
|
||||
}
|
||||
|
||||
if (aCallState == nsITelephone::CALL_STATE_DISCONNECTED) {
|
||||
if (aCallState == nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED) {
|
||||
NS_ASSERTION(mLive, "Should be live!");
|
||||
mTelephony->RemoveCall(this);
|
||||
mLive = false;
|
||||
@ -208,33 +208,33 @@ TelephonyCall::GetState(nsAString& aState)
|
||||
NS_IMETHODIMP
|
||||
TelephonyCall::Answer()
|
||||
{
|
||||
if (mCallState != nsITelephone::CALL_STATE_INCOMING) {
|
||||
if (mCallState != nsIRadioInterfaceLayer::CALL_STATE_INCOMING) {
|
||||
NS_WARNING("Answer on non-incoming call ignored!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mTelephony->Telephone()->AnswerCall(mCallIndex);
|
||||
nsresult rv = mTelephony->RIL()->AnswerCall(mCallIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ChangeStateInternal(nsITelephone::CALL_STATE_CONNECTING, true);
|
||||
ChangeStateInternal(nsIRadioInterfaceLayer::CALL_STATE_CONNECTING, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelephonyCall::HangUp()
|
||||
{
|
||||
if (mCallState == nsITelephone::CALL_STATE_DISCONNECTING ||
|
||||
mCallState == nsITelephone::CALL_STATE_DISCONNECTED) {
|
||||
if (mCallState == nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTING ||
|
||||
mCallState == nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED) {
|
||||
NS_WARNING("HangUp on previously disconnected call ignored!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mCallState == nsITelephone::CALL_STATE_INCOMING ?
|
||||
mTelephony->Telephone()->RejectCall(mCallIndex) :
|
||||
mTelephony->Telephone()->HangUp(mCallIndex);
|
||||
nsresult rv = mCallState == nsIRadioInterfaceLayer::CALL_STATE_INCOMING ?
|
||||
mTelephony->RIL()->RejectCall(mCallIndex) :
|
||||
mTelephony->RIL()->HangUp(mCallIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ChangeStateInternal(nsITelephone::CALL_STATE_DISCONNECTING, true);
|
||||
ChangeStateInternal(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTING, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "TelephonyCommon.h"
|
||||
|
||||
#include "nsIDOMTelephonyCall.h"
|
||||
#include "nsITelephone.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
@ -131,7 +131,7 @@ public:
|
||||
private:
|
||||
TelephonyCall()
|
||||
: mCallIndex(kOutgoingPlaceholderCallIndex),
|
||||
mCallState(nsITelephone::CALL_STATE_UNKNOWN), mLive(false), mOutgoing(false)
|
||||
mCallState(nsIRadioInterfaceLayer::CALL_STATE_UNKNOWN), mLive(false), mOutgoing(false)
|
||||
{ }
|
||||
|
||||
~TelephonyCall()
|
||||
|
@ -1 +0,0 @@
|
||||
component {2d831c8d-6017-435b-a80c-e5d422810cea} nsTelephonyWorker.js
|
@ -14,8 +14,8 @@ SimpleTest.waitForFocus(function () opener.framesetWindowLoaded(window));
|
||||
<frame src="data:text/html,<html id='f7'><body id='framebody4'><input id='f8'><body></html>">
|
||||
</frameset>
|
||||
<noframes>
|
||||
<input id="unusued1"/>
|
||||
<input id="unusued2" tabindex="1"/>
|
||||
<input id="unused1"/>
|
||||
<input id="unused2" tabindex="1"/>
|
||||
</noframes>
|
||||
</frameset>
|
||||
|
||||
|
@ -113,7 +113,8 @@ public class GeckoAppShell
|
||||
public static native void onLowMemory();
|
||||
public static native void callObserver(String observerKey, String topic, String data);
|
||||
public static native void removeObserver(String observerKey);
|
||||
public static native void loadLibs(String apkName, boolean shouldExtract);
|
||||
public static native void loadGeckoLibsNative(String apkName);
|
||||
public static native void loadSQLiteLibsNative(String apkName, boolean shouldExtract);
|
||||
public static native void onChangeNetworkLinkStatus(String status);
|
||||
public static native void reportJavaCrash(String stack);
|
||||
|
||||
@ -396,7 +397,8 @@ public class GeckoAppShell
|
||||
}
|
||||
}
|
||||
}
|
||||
loadLibs(apkName, extractLibs);
|
||||
loadSQLiteLibsNative(apkName, extractLibs);
|
||||
loadGeckoLibsNative(apkName);
|
||||
}
|
||||
|
||||
private static void putLocaleEnv() {
|
||||
|
@ -116,6 +116,7 @@ DrawTargetCG::~DrawTargetCG()
|
||||
CGColorSpaceRelease(mColorSpace);
|
||||
if (mCg)
|
||||
CGContextRelease(mCg);
|
||||
free(mData);
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
@ -845,7 +846,6 @@ DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
|
||||
// XXX: currently we allocate ourselves so that we can easily return a gfxImageSurface
|
||||
// we might not need to later if once we don't need to support gfxImageSurface
|
||||
//XXX: currently Init implicitly clears, that can often be a waste of time
|
||||
// XXX: leaked
|
||||
mData = calloc(mSize.height * stride, 1);
|
||||
// XXX: what should we do if this fails?
|
||||
mCg = CGBitmapContextCreate (mData,
|
||||
|
@ -131,12 +131,19 @@ endif
|
||||
EXPORTS_NAMESPACES = gfxipc mozilla/layers
|
||||
EXPORTS_gfxipc = ShadowLayerUtils.h
|
||||
EXPORTS_mozilla/layers =\
|
||||
CompositorCocoaWidgetHelper.h \
|
||||
CompositorChild.h \
|
||||
CompositorParent.h \
|
||||
ShadowLayers.h \
|
||||
ShadowLayersChild.h \
|
||||
ShadowLayersParent.h \
|
||||
ShadowLayersManager.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
CompositorCocoaWidgetHelper.cpp \
|
||||
CompositorChild.cpp \
|
||||
CompositorParent.cpp \
|
||||
ShadowLayers.cpp \
|
||||
ShadowLayerChild.cpp \
|
||||
ShadowLayersChild.cpp \
|
||||
|
@ -50,7 +50,11 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
||||
gfxASurface *aSurface,
|
||||
const gfxIntSize &aSize)
|
||||
{
|
||||
if (aSurface && aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
|
||||
if (!aSurface) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
|
||||
void *data = aSurface->GetData(&gKeyD3D10Texture);
|
||||
if (data) {
|
||||
nsRefPtr<ID3D10Texture2D> texture = static_cast<ID3D10Texture2D*>(data);
|
||||
@ -67,7 +71,7 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
||||
if (!imageSurface) {
|
||||
imageSurface = new gfxImageSurface(aSize,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
context->SetSource(aSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
@ -75,13 +79,13 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
||||
}
|
||||
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
imageSurface->GetSize().width,
|
||||
imageSurface->GetSize().height,
|
||||
1, 1);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
|
||||
data.pSysMem = imageSurface->Data();
|
||||
data.SysMemPitch = imageSurface->Stride();
|
||||
|
||||
|
93
gfx/layers/ipc/CompositorChild.cpp
Normal file
93
gfx/layers/ipc/CompositorChild.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CompositorChild.h"
|
||||
#include "CompositorParent.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "mozilla/layers/ShadowLayersChild.h"
|
||||
|
||||
using mozilla::layers::ShadowLayersChild;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
CompositorChild::CompositorChild(LayerManager *aLayerManager)
|
||||
: mLayerManager(aLayerManager)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositorChild);
|
||||
}
|
||||
|
||||
CompositorChild::~CompositorChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositorChild);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorChild::Destroy()
|
||||
{
|
||||
mLayerManager = NULL;
|
||||
size_t numChildren = ManagedPLayersChild().Length();
|
||||
NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren,
|
||||
"compositor must only have 0 or 1 layer forwarder");
|
||||
|
||||
if (numChildren) {
|
||||
ShadowLayersChild* layers =
|
||||
static_cast<ShadowLayersChild*>(ManagedPLayersChild()[0]);
|
||||
layers->Destroy();
|
||||
}
|
||||
SendStop();
|
||||
}
|
||||
|
||||
PLayersChild*
|
||||
CompositorChild::AllocPLayers(const LayersBackend &backend)
|
||||
{
|
||||
return new ShadowLayersChild();
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorChild::DeallocPLayers(PLayersChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
73
gfx/layers/ipc/CompositorChild.h
Normal file
73
gfx/layers/ipc/CompositorChild.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_CompositorChild_h
|
||||
#define mozilla_layers_CompositorChild_h
|
||||
|
||||
#include "mozilla/layers/PCompositorChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class LayerManager;
|
||||
class CompositorParent;
|
||||
|
||||
class CompositorChild : public PCompositorChild
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(CompositorChild)
|
||||
public:
|
||||
CompositorChild(LayerManager *aLayerManager);
|
||||
virtual ~CompositorChild();
|
||||
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
virtual PLayersChild* AllocPLayers(const LayersBackend &aBackend);
|
||||
virtual bool DeallocPLayers(PLayersChild *aChild);
|
||||
|
||||
private:
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CompositorChild);
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_layers_CompositorChild_h
|
58
gfx/layers/ipc/CompositorCocoaWidgetHelper.cpp
Normal file
58
gfx/layers/ipc/CompositorCocoaWidgetHelper.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CompositorParent.h"
|
||||
#include "CompositorCocoaWidgetHelper.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
namespace compositor {
|
||||
|
||||
LayerManager*
|
||||
GetLayerManager(CompositorParent* aParent)
|
||||
{
|
||||
return aParent->GetLayerManager();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
63
gfx/layers/ipc/CompositorCocoaWidgetHelper.h
Normal file
63
gfx/layers/ipc/CompositorCocoaWidgetHelper.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_CompositorCocoaWidgetHelper_h
|
||||
#define mozilla_layers_CompositorCocoaWidgetHelper_h
|
||||
|
||||
// Note we can't include IPDL-generated headers here, since this file is being
|
||||
// used as a workaround for Bug 719036.
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class CompositorParent;
|
||||
class LayerManager;
|
||||
|
||||
namespace compositor {
|
||||
|
||||
// Needed when we cannot directly include CompositorParent.h since it includes
|
||||
// an IPDL-generated header (e.g. in widget/cocoa/nsChildView.mm; see Bug 719036).
|
||||
LayerManager* GetLayerManager(CompositorParent* aParent);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // mozilla_layers_CompositorCocoaWidgetHelper_h
|
||||
|
159
gfx/layers/ipc/CompositorParent.cpp
Normal file
159
gfx/layers/ipc/CompositorParent.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "CompositorParent.h"
|
||||
#include "ShadowLayersParent.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
CompositorParent::CompositorParent(nsIWidget* aWidget)
|
||||
: mStopped(false), mWidget(aWidget)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CompositorParent);
|
||||
}
|
||||
|
||||
CompositorParent::~CompositorParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositorParent);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::Destroy()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(ManagedPLayersParent().Length() == 0,
|
||||
"CompositorParent destroyed before managed PLayersParent");
|
||||
|
||||
// Ensure that the layer manager is destroyed on the compositor thread.
|
||||
mLayerManager = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvStop()
|
||||
{
|
||||
mStopped = true;
|
||||
Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::ScheduleComposition()
|
||||
{
|
||||
CancelableTask *composeTask = NewRunnableMethod(this, &CompositorParent::Composite);
|
||||
MessageLoop::current()->PostTask(FROM_HERE, composeTask);
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::Composite()
|
||||
{
|
||||
if (mStopped || !mLayerManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLayerManager->EndEmptyTransaction();
|
||||
}
|
||||
|
||||
// Go down shadow layer tree, setting properties to match their non-shadow
|
||||
// counterparts.
|
||||
static void
|
||||
SetShadowProperties(Layer* aLayer)
|
||||
{
|
||||
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
|
||||
ShadowLayer* shadow = aLayer->AsShadowLayer();
|
||||
shadow->SetShadowTransform(aLayer->GetTransform());
|
||||
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
|
||||
shadow->SetShadowClipRect(aLayer->GetClipRect());
|
||||
|
||||
for (Layer* child = aLayer->GetFirstChild();
|
||||
child; child = child->GetNextSibling()) {
|
||||
SetShadowProperties(child);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::ShadowLayersUpdated()
|
||||
{
|
||||
const nsTArray<PLayersParent*>& shadowParents = ManagedPLayersParent();
|
||||
NS_ABORT_IF_FALSE(shadowParents.Length() <= 1,
|
||||
"can only support at most 1 ShadowLayersParent");
|
||||
if (shadowParents.Length()) {
|
||||
Layer* root = static_cast<ShadowLayersParent*>(shadowParents[0])->GetRoot();
|
||||
mLayerManager->SetRoot(root);
|
||||
SetShadowProperties(root);
|
||||
}
|
||||
ScheduleComposition();
|
||||
}
|
||||
|
||||
PLayersParent*
|
||||
CompositorParent::AllocPLayers(const LayersBackend &backendType)
|
||||
{
|
||||
if (backendType == LayerManager::LAYERS_OPENGL) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(mWidget);
|
||||
mWidget = NULL;
|
||||
mLayerManager = layerManager;
|
||||
|
||||
if (!layerManager->Initialize()) {
|
||||
NS_ERROR("Failed to init OGL Layers");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ShadowLayerManager* slm = layerManager->AsShadowManager();
|
||||
if (!slm) {
|
||||
return NULL;
|
||||
}
|
||||
return new ShadowLayersParent(slm, this);
|
||||
} else {
|
||||
NS_ERROR("Unsupported backend selected for Async Compositor");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::DeallocPLayers(PLayersParent* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
88
gfx/layers/ipc/CompositorParent.h
Normal file
88
gfx/layers/ipc/CompositorParent.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_CompositorParent_h
|
||||
#define mozilla_layers_CompositorParent_h
|
||||
|
||||
#include "mozilla/layers/PCompositorParent.h"
|
||||
#include "mozilla/layers/PLayersParent.h"
|
||||
#include "ShadowLayersManager.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class LayerManager;
|
||||
|
||||
class CompositorParent : public PCompositorParent,
|
||||
public ShadowLayersManager
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
|
||||
public:
|
||||
CompositorParent(nsIWidget* aWidget);
|
||||
virtual ~CompositorParent();
|
||||
|
||||
virtual bool RecvStop() MOZ_OVERRIDE;
|
||||
|
||||
virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
|
||||
void Destroy();
|
||||
|
||||
LayerManager* GetLayerManager() { return mLayerManager; }
|
||||
|
||||
protected:
|
||||
virtual PLayersParent* AllocPLayers(const LayersBackend &backendType);
|
||||
virtual bool DeallocPLayers(PLayersParent* aLayers);
|
||||
|
||||
private:
|
||||
void ScheduleComposition();
|
||||
void Composite();
|
||||
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
bool mStopped;
|
||||
nsIWidget* mWidget;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_layers_CompositorParent_h
|
71
gfx/layers/ipc/PCompositor.ipdl
Normal file
71
gfx/layers/ipc/PCompositor.ipdl
Normal file
@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benoit Girard <bgirard@mozilla.com>
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
include protocol PLayers;
|
||||
|
||||
using mozilla::LayersBackend;
|
||||
using mozilla::null_t;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* The PCompositor protocol is used to manage communication between
|
||||
* the main thread and the compositor thread context. It's primary
|
||||
* purpose is to manage the PLayers sub protocol.
|
||||
*/
|
||||
// This should really be 'sync', but we're using 'rpc' as a workaround
|
||||
// for Bug 716631.
|
||||
rpc protocol PCompositor
|
||||
{
|
||||
// A Compositor manages a single Layer Manager (PLayers)
|
||||
manages PLayers;
|
||||
|
||||
parent:
|
||||
|
||||
// Clean up in preparation for destruction.
|
||||
sync Stop();
|
||||
|
||||
sync PLayers(LayersBackend backend);
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
@ -38,7 +38,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
//include protocol PCompositor;
|
||||
include protocol PCompositor;
|
||||
include protocol PLayer;
|
||||
include protocol PRenderFrame;
|
||||
|
||||
@ -226,7 +226,7 @@ union EditReply {
|
||||
|
||||
|
||||
sync protocol PLayers {
|
||||
manager PRenderFrame /*or PCompositor or PMedia or PPlugin*/;
|
||||
manager PRenderFrame or PCompositor;
|
||||
manages PLayer;
|
||||
|
||||
parent:
|
||||
|
63
gfx/layers/ipc/ShadowLayersManager.h
Normal file
63
gfx/layers/ipc/ShadowLayersManager.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Content App.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ali Juma <ajuma@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_layers_ShadowLayersManager_h
|
||||
#define mozilla_layers_ShadowLayersManager_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layout {
|
||||
class RenderFrameParent;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
class CompositorParent;
|
||||
|
||||
class ShadowLayersManager
|
||||
{
|
||||
|
||||
public:
|
||||
virtual void ShadowLayersUpdated() = 0;
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_layers_ShadowLayersManager_h
|
@ -47,6 +47,7 @@
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "mozilla/layout/RenderFrameParent.h"
|
||||
#include "CompositorParent.h"
|
||||
|
||||
#include "gfxSharedImageSurface.h"
|
||||
|
||||
@ -121,11 +122,11 @@ ShadowChild(const OpRemoveChild& op)
|
||||
|
||||
//--------------------------------------------------
|
||||
// ShadowLayersParent
|
||||
ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager)
|
||||
: mDestroyed(false)
|
||||
ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager,
|
||||
ShadowLayersManager* aLayersManager)
|
||||
: mLayerManager(aManager), mShadowLayersManager(aLayersManager), mDestroyed(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ShadowLayersParent);
|
||||
mLayerManager = aManager;
|
||||
}
|
||||
|
||||
ShadowLayersParent::~ShadowLayersParent()
|
||||
@ -382,7 +383,7 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
||||
// other's buffer contents.
|
||||
ShadowLayerManager::PlatformSyncBeforeReplyUpdate();
|
||||
|
||||
Frame()->ShadowLayersUpdated();
|
||||
mShadowLayersManager->ShadowLayersUpdated();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -400,12 +401,6 @@ ShadowLayersParent::DeallocPLayer(PLayerParent* actor)
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderFrameParent*
|
||||
ShadowLayersParent::Frame()
|
||||
{
|
||||
return static_cast<RenderFrameParent*>(Manager());
|
||||
}
|
||||
|
||||
void
|
||||
ShadowLayersParent::DestroySharedSurface(gfxSharedImageSurface* aSurface)
|
||||
{
|
||||
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include "mozilla/layers/PLayersParent.h"
|
||||
#include "ShadowLayers.h"
|
||||
#include "ShadowLayersManager.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -63,7 +64,7 @@ class ShadowLayersParent : public PLayersParent,
|
||||
typedef InfallibleTArray<EditReply> EditReplyArray;
|
||||
|
||||
public:
|
||||
ShadowLayersParent(ShadowLayerManager* aManager);
|
||||
ShadowLayersParent(ShadowLayerManager* aManager, ShadowLayersManager* aLayersManager);
|
||||
~ShadowLayersParent();
|
||||
|
||||
void Destroy();
|
||||
@ -83,9 +84,8 @@ protected:
|
||||
NS_OVERRIDE virtual bool DeallocPLayer(PLayerParent* actor);
|
||||
|
||||
private:
|
||||
RenderFrameParent* Frame();
|
||||
|
||||
nsRefPtr<ShadowLayerManager> mLayerManager;
|
||||
ShadowLayersManager* mShadowLayersManager;
|
||||
// Hold the root because it might be grafted under various
|
||||
// containers in the "real" layer tree
|
||||
nsRefPtr<ContainerLayer> mRoot;
|
||||
|
@ -1,4 +1,5 @@
|
||||
IPDLSRCS = \
|
||||
PCompositor.ipdl \
|
||||
PLayer.ipdl \
|
||||
PLayers.ipdl \
|
||||
$(NULL)
|
||||
|
@ -1410,8 +1410,6 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
||||
continue;
|
||||
}
|
||||
|
||||
aClip.RemoveRoundedCorners();
|
||||
|
||||
// Just use its layer.
|
||||
nsRefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, mParameters);
|
||||
if (!ownLayer) {
|
||||
@ -1435,10 +1433,13 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
||||
NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager");
|
||||
NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData),
|
||||
"We shouldn't have a FrameLayerBuilder-managed layer here!");
|
||||
NS_ASSERTION(aClip.mHaveClipRect ||
|
||||
aClip.mRoundedClipRects.IsEmpty(),
|
||||
"If we have rounded rects, we must have a clip rect");
|
||||
// It has its own layer. Update that layer's clip and visible rects.
|
||||
if (aClip.mHaveClipRect) {
|
||||
ownLayer->IntersectClipRect(
|
||||
aClip.mClipRect.ScaleToNearestPixels(
|
||||
aClip.NonRoundedIntersection().ScaleToNearestPixels(
|
||||
mParameters.mXScale, mParameters.mYScale, appUnitsPerDevPixel));
|
||||
}
|
||||
ThebesLayerData* data = GetTopThebesLayerData();
|
||||
@ -2364,7 +2365,6 @@ FrameLayerBuilder::Clip::IsRectClippedByRoundedCorner(const nsRect& aRect) const
|
||||
nsRect
|
||||
FrameLayerBuilder::Clip::NonRoundedIntersection() const
|
||||
{
|
||||
NS_ASSERTION(!mRoundedClipRects.IsEmpty(), "no rounded clip rects?");
|
||||
nsRect result = mClipRect;
|
||||
for (PRUint32 i = 0, iEnd = mRoundedClipRects.Length();
|
||||
i < iEnd; ++i) {
|
||||
|
@ -648,7 +648,7 @@ RenderFrameParent::AllocPLayers(LayerManager::LayersBackend* aBackendType)
|
||||
return nsnull;
|
||||
}
|
||||
*aBackendType = lm->GetBackendType();
|
||||
return new ShadowLayersParent(slm);
|
||||
return new ShadowLayersParent(slm, this);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define mozilla_layout_RenderFrameParent_h
|
||||
|
||||
#include "mozilla/layout/PRenderFrameParent.h"
|
||||
#include "mozilla/layers/ShadowLayersManager.h"
|
||||
|
||||
#include <map>
|
||||
#include "nsDisplayList.h"
|
||||
@ -59,7 +60,8 @@ class ShadowLayersParent;
|
||||
|
||||
namespace layout {
|
||||
|
||||
class RenderFrameParent : public PRenderFrameParent
|
||||
class RenderFrameParent : public PRenderFrameParent,
|
||||
public mozilla::layers::ShadowLayersManager
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
typedef mozilla::layers::ContainerLayer ContainerLayer;
|
||||
@ -84,7 +86,7 @@ public:
|
||||
|
||||
void ContentViewScaleChanged(nsContentView* aView);
|
||||
|
||||
void ShadowLayersUpdated();
|
||||
virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
|
||||
|
||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
nsSubDocumentFrame* aFrame,
|
||||
|
47
layout/reftests/bugs/718521-ref.html
Normal file
47
layout/reftests/bugs/718521-ref.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rounded rectangle clipping test</title>
|
||||
<style>
|
||||
.clipround {
|
||||
left:100px;
|
||||
top:100px;
|
||||
position:absolute;
|
||||
width:700px;
|
||||
height:380px;
|
||||
overflow:hidden;
|
||||
border-radius:45px;
|
||||
}
|
||||
.greendiv {
|
||||
width:300px;
|
||||
height:230px;
|
||||
background-color:#008000;
|
||||
position:absolute;
|
||||
}
|
||||
#nrcDiv0 {
|
||||
left:0px;
|
||||
top:0px;
|
||||
}
|
||||
#nrcDiv1 {
|
||||
left:320px;
|
||||
top:0px;
|
||||
}
|
||||
#nrcDiv2 {
|
||||
left:0px;
|
||||
top:240px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="clipround">
|
||||
<div id="nrcDiv0" class="greendiv"></div>
|
||||
</div>
|
||||
<div class="clipround">
|
||||
<div id="nrcDiv1" class="greendiv"></div>
|
||||
</div>
|
||||
<div class="clipround">
|
||||
<div id="nrcDiv2" class="greendiv"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
52
layout/reftests/bugs/718521.html
Normal file
52
layout/reftests/bugs/718521.html
Normal file
@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rounded rectangle clipping test</title>
|
||||
<style>
|
||||
.clipround {
|
||||
left:100px;
|
||||
top:100px;
|
||||
position:absolute;
|
||||
width:700px;
|
||||
height:380px;
|
||||
overflow:hidden;
|
||||
border-radius:45px;
|
||||
}
|
||||
canvas {
|
||||
position:absolute;
|
||||
}
|
||||
#nrcCanvas0 {
|
||||
left:0px;
|
||||
top:0px;
|
||||
}
|
||||
#nrcCanvas1 {
|
||||
left:320px;
|
||||
top:0px;
|
||||
}
|
||||
#nrcCanvas2 {
|
||||
left:0px;
|
||||
top:240px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="clipround">
|
||||
<canvas id="nrcCanvas0" width="320" height="260"></canvas>
|
||||
<canvas id="nrcCanvas1" width="320" height="260"></canvas>
|
||||
<canvas id="nrcCanvas2" width="320" height="260"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
drawShapes('nrcCanvas0');
|
||||
drawShapes('nrcCanvas1');
|
||||
drawShapes('nrcCanvas2');
|
||||
|
||||
function drawShapes(elName) {
|
||||
var ctxt = document.getElementById(elName).getContext('2d');
|
||||
ctxt.fillStyle = '#008000';
|
||||
ctxt.fillRect(0, 0, 300, 230);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1688,3 +1688,4 @@ needs-focus != 703186-1.html 703186-2.html
|
||||
== 714519-1-q.html 714519-1-ref.html
|
||||
== 714519-2-as.html 714519-2-ref.html
|
||||
== 714519-2-q.html 714519-2-ref.html
|
||||
fuzzy == 718521.html 718521-ref.html
|
||||
|
@ -173,7 +173,7 @@ public class AboutHomeContent extends ScrollView {
|
||||
activity.stopManagingCursor(mCursor);
|
||||
|
||||
ContentResolver resolver = GeckoApp.mAppContext.getContentResolver();
|
||||
mCursor = BrowserDB.filter(resolver, "", NUMBER_OF_TOP_SITES_PORTRAIT, "about:%");
|
||||
mCursor = BrowserDB.getTopSites(resolver, NUMBER_OF_TOP_SITES_PORTRAIT);
|
||||
activity.startManagingCursor(mCursor);
|
||||
|
||||
mTopSitesAdapter = new TopSitesCursorAdapter(activity,
|
||||
|
@ -893,7 +893,8 @@ abstract public class GeckoApp
|
||||
if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
|
||||
if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
|
||||
Log.i(LOGTAG, "Got a document start");
|
||||
handleDocumentStart(tabId);
|
||||
final boolean showProgress = message.getBoolean("showProgress");
|
||||
handleDocumentStart(tabId, showProgress);
|
||||
} else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
|
||||
Log.i(LOGTAG, "Got a document stop");
|
||||
handleDocumentStop(tabId);
|
||||
@ -1181,7 +1182,7 @@ abstract public class GeckoApp
|
||||
});
|
||||
}
|
||||
|
||||
void handleDocumentStart(int tabId) {
|
||||
void handleDocumentStart(int tabId, final boolean showProgress) {
|
||||
final Tab tab = Tabs.getInstance().getTab(tabId);
|
||||
if (tab == null)
|
||||
return;
|
||||
@ -1193,7 +1194,8 @@ abstract public class GeckoApp
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
|
||||
mBrowserToolbar.setProgressVisibility(true);
|
||||
if (showProgress)
|
||||
mBrowserToolbar.setProgressVisibility(true);
|
||||
}
|
||||
onTabsChanged(tab);
|
||||
}
|
||||
@ -2099,9 +2101,10 @@ abstract public class GeckoApp
|
||||
File profileDir = getProfileDir();
|
||||
if (profileDir != null) {
|
||||
Log.i(LOGTAG, "checking profile migration in: " + profileDir.getAbsolutePath());
|
||||
final GeckoApp app = GeckoApp.mAppContext;
|
||||
GeckoAppShell.ensureSQLiteLibsLoaded(app.getApplication().getPackageResourcePath());
|
||||
ProfileMigrator profileMigrator =
|
||||
new ProfileMigrator(GeckoApp.mAppContext.getContentResolver(),
|
||||
profileDir);
|
||||
new ProfileMigrator(app.getContentResolver(), profileDir);
|
||||
profileMigrator.launchBackground();
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ public class GeckoAppShell
|
||||
static private int sFreeSpace = -1;
|
||||
static File sHomeDir = null;
|
||||
static private int sDensityDpi = 0;
|
||||
private static Boolean sSQLiteLibsLoaded = false;
|
||||
|
||||
private static HashMap<String, ArrayList<GeckoEventListener>> mEventListeners;
|
||||
|
||||
@ -129,7 +130,8 @@ public class GeckoAppShell
|
||||
public static native void onLowMemory();
|
||||
public static native void callObserver(String observerKey, String topic, String data);
|
||||
public static native void removeObserver(String observerKey);
|
||||
public static native void loadLibs(String apkName, boolean shouldExtract);
|
||||
public static native void loadGeckoLibsNative(String apkName);
|
||||
public static native void loadSQLiteLibsNative(String apkName, boolean shouldExtract);
|
||||
public static native void onChangeNetworkLinkStatus(String status);
|
||||
public static native void reportJavaCrash(String stack);
|
||||
public static void notifyUriVisited(String uri) {
|
||||
@ -310,7 +312,7 @@ public class GeckoAppShell
|
||||
}
|
||||
|
||||
// java-side stuff
|
||||
public static void loadGeckoLibs(String apkName) {
|
||||
public static boolean loadLibsSetup(String apkName) {
|
||||
// The package data lib directory isn't placed in ld.so's
|
||||
// search path, so we have to manually load libraries that
|
||||
// libxul will depend on. Not ideal.
|
||||
@ -415,7 +417,23 @@ public class GeckoAppShell
|
||||
}
|
||||
}
|
||||
}
|
||||
loadLibs(apkName, extractLibs);
|
||||
return extractLibs;
|
||||
}
|
||||
|
||||
public static void ensureSQLiteLibsLoaded(String apkName) {
|
||||
if (sSQLiteLibsLoaded)
|
||||
return;
|
||||
synchronized(sSQLiteLibsLoaded) {
|
||||
if (sSQLiteLibsLoaded)
|
||||
return;
|
||||
loadSQLiteLibsNative(apkName, loadLibsSetup(apkName));
|
||||
sSQLiteLibsLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadGeckoLibs(String apkName) {
|
||||
boolean extractLibs = loadLibsSetup(apkName);
|
||||
loadGeckoLibsNative(apkName);
|
||||
}
|
||||
|
||||
private static void putLocaleEnv() {
|
||||
|
@ -86,8 +86,9 @@ public class GeckoThread extends Thread {
|
||||
// At some point while loading the gecko libs our default locale gets set
|
||||
// so just save it to locale here and reset it as default after the join
|
||||
Locale locale = Locale.getDefault();
|
||||
GeckoAppShell.loadGeckoLibs(
|
||||
app.getApplication().getPackageResourcePath());
|
||||
String resourcePath = app.getApplication().getPackageResourcePath();
|
||||
GeckoAppShell.ensureSQLiteLibsLoaded(resourcePath);
|
||||
GeckoAppShell.loadGeckoLibs(resourcePath);
|
||||
Locale.setDefault(locale);
|
||||
Resources res = app.getBaseContext().getResources();
|
||||
Configuration config = res.getConfiguration();
|
||||
|
@ -89,6 +89,9 @@ FENNEC_JAVA_FILES = \
|
||||
LinkPreference.java \
|
||||
ProfileMigrator.java \
|
||||
PromptService.java \
|
||||
sqlite/ByteBufferInputStream.java \
|
||||
sqlite/SQLiteBridge.java \
|
||||
sqlite/SQLiteBridgeException.java \
|
||||
SurfaceLockInfo.java \
|
||||
Tab.java \
|
||||
Tabs.java \
|
||||
|
@ -15,7 +15,7 @@
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009-2010
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
@ -38,24 +38,22 @@
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.sqlite.ByteBufferInputStream;
|
||||
import org.mozilla.gecko.sqlite.SQLiteBridge;
|
||||
import org.mozilla.gecko.sqlite.SQLiteBridgeException;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.Browser;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebIconDatabase;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -70,7 +68,6 @@ public class ProfileMigrator {
|
||||
private static final String LOGTAG = "ProfMigr";
|
||||
private File mProfileDir;
|
||||
private ContentResolver mCr;
|
||||
private SQLiteDatabase mDb;
|
||||
|
||||
/*
|
||||
Amount of Android history entries we will remember
|
||||
@ -82,32 +79,32 @@ public class ProfileMigrator {
|
||||
These queries are derived from the low-level Places schema
|
||||
https://developer.mozilla.org/en/The_Places_database
|
||||
*/
|
||||
final String bookmarkQuery = "SELECT places.url AS a_url, "
|
||||
private final String bookmarkQuery = "SELECT places.url AS a_url, "
|
||||
+ "places.title AS a_title FROM "
|
||||
+ "(moz_places as places JOIN moz_bookmarks as bookmarks ON "
|
||||
+ "places.id = bookmarks.fk) WHERE places.hidden <> 1 "
|
||||
+ "ORDER BY bookmarks.dateAdded";
|
||||
// Don't ask why. Just curse along at the Android devs.
|
||||
final String bookmarkUrl = "a_url";
|
||||
final String bookmarkTitle = "a_title";
|
||||
// Result column of relevant data
|
||||
private final String bookmarkUrl = "a_url";
|
||||
private final String bookmarkTitle = "a_title";
|
||||
|
||||
final String historyQuery =
|
||||
private final String historyQuery =
|
||||
"SELECT places.url AS a_url, places.title AS a_title, "
|
||||
+ "history.visit_date AS a_date FROM "
|
||||
+ "(moz_historyvisits AS history JOIN moz_places AS places ON "
|
||||
+ "places.id = history.place_id) WHERE places.hidden <> 1 "
|
||||
+ "ORDER BY history.visit_date DESC";
|
||||
final String historyUrl = "a_url";
|
||||
final String historyTitle = "a_title";
|
||||
final String historyDate = "a_date";
|
||||
private final String historyUrl = "a_url";
|
||||
private final String historyTitle = "a_title";
|
||||
private final String historyDate = "a_date";
|
||||
|
||||
final String faviconQuery =
|
||||
private final String faviconQuery =
|
||||
"SELECT places.url AS a_url, favicon.data AS a_data, "
|
||||
+ "favicon.mime_type AS a_mime FROM (moz_places AS places JOIN "
|
||||
+ "moz_favicons AS favicon ON places.favicon_id = favicon.id)";
|
||||
final String faviconUrl = "a_url";
|
||||
final String faviconData = "a_data";
|
||||
final String faviconMime = "a_mime";
|
||||
private final String faviconUrl = "a_url";
|
||||
private final String faviconData = "a_data";
|
||||
private final String faviconMime = "a_mime";
|
||||
|
||||
public ProfileMigrator(ContentResolver cr, File profileDir) {
|
||||
mProfileDir = profileDir;
|
||||
@ -116,12 +113,8 @@ public class ProfileMigrator {
|
||||
|
||||
public void launchBackground() {
|
||||
// Work around http://code.google.com/p/android/issues/detail?id=11291
|
||||
// The WebIconDatabase needs to be initialized within the UI thread so
|
||||
// just request the instance here.
|
||||
WebIconDatabase.getInstance();
|
||||
|
||||
PlacesTask placesTask = new PlacesTask();
|
||||
new Thread(placesTask).start();
|
||||
// WebIconDatabase needs to be initialized within a looper thread.
|
||||
GeckoAppShell.getHandler().post(new PlacesTask());
|
||||
}
|
||||
|
||||
private class PlacesTask implements Runnable {
|
||||
@ -177,37 +170,24 @@ public class ProfileMigrator {
|
||||
}
|
||||
}
|
||||
|
||||
protected void migrateHistory(SQLiteDatabase db) {
|
||||
protected void migrateHistory(SQLiteBridge db) {
|
||||
Map<String, Long> androidHistory = gatherAndroidHistory();
|
||||
final ArrayList<String> placesHistory = new ArrayList<String>();
|
||||
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor =
|
||||
db.rawQuery(historyQuery, new String[] { });
|
||||
final int urlCol =
|
||||
cursor.getColumnIndexOrThrow(historyUrl);
|
||||
final int titleCol =
|
||||
cursor.getColumnIndexOrThrow(historyTitle);
|
||||
final int dateCol =
|
||||
cursor.getColumnIndexOrThrow(historyDate);
|
||||
ArrayList<Object[]> queryResult = db.query(historyQuery);
|
||||
final int urlCol = db.getColumnIndex(historyUrl);
|
||||
final int titleCol = db.getColumnIndex(historyTitle);
|
||||
final int dateCol = db.getColumnIndex(historyDate);
|
||||
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
String url = cursor.getString(urlCol);
|
||||
String title = cursor.getString(titleCol);
|
||||
// Convert from us (Places) to ms (Java, Android)
|
||||
long date = cursor.getLong(dateCol) / (long)1000;
|
||||
for (Object[] resultRow: queryResult) {
|
||||
String url = (String)resultRow[urlCol];
|
||||
String title = (String)resultRow[titleCol];
|
||||
long date = Long.parseLong((String)(resultRow[dateCol])) / (long)1000;
|
||||
addHistory(androidHistory, url, title, date);
|
||||
placesHistory.add(url);
|
||||
cursor.moveToNext();
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
} catch (SQLiteException e) {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
} catch (SQLiteBridgeException e) {
|
||||
Log.i(LOGTAG, "Failed to get bookmarks: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
@ -231,90 +211,55 @@ public class ProfileMigrator {
|
||||
}
|
||||
}
|
||||
|
||||
protected void migrateBookmarks(SQLiteDatabase db) {
|
||||
Cursor cursor = null;
|
||||
protected void migrateBookmarks(SQLiteBridge db) {
|
||||
try {
|
||||
cursor = db.rawQuery(bookmarkQuery,
|
||||
new String[] {});
|
||||
if (cursor.getCount() > 0) {
|
||||
final int urlCol =
|
||||
cursor.getColumnIndexOrThrow(bookmarkUrl);
|
||||
final int titleCol =
|
||||
cursor.getColumnIndexOrThrow(bookmarkTitle);
|
||||
ArrayList<Object[]> queryResult = db.query(bookmarkQuery);
|
||||
final int urlCol = db.getColumnIndex(bookmarkUrl);
|
||||
final int titleCol = db.getColumnIndex(bookmarkTitle);
|
||||
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
String url = cursor.getString(urlCol);
|
||||
String title = cursor.getString(titleCol);
|
||||
addBookmark(url, title);
|
||||
cursor.moveToNext();
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
} catch (SQLiteException e) {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
for (Object[] resultRow: queryResult) {
|
||||
String url = (String)resultRow[urlCol];
|
||||
String title = (String)resultRow[titleCol];
|
||||
addBookmark(url, title);
|
||||
}
|
||||
} catch (SQLiteBridgeException e) {
|
||||
Log.i(LOGTAG, "Failed to get bookmarks: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected void addFavicon(String url, String mime, byte[] data) {
|
||||
ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
|
||||
protected void addFavicon(String url, String mime, ByteBuffer data) {
|
||||
ByteBufferInputStream byteStream = new ByteBufferInputStream(data);
|
||||
BitmapDrawable image = (BitmapDrawable) Drawable.createFromStream(byteStream, "src");
|
||||
if (image != null) {
|
||||
try {
|
||||
BrowserDB.updateFaviconForUrl(mCr, url, image);
|
||||
} catch (SQLiteException e) {
|
||||
} catch (SQLException e) {
|
||||
Log.i(LOGTAG, "Migrating favicon failed: " + mime + " URL: " + url
|
||||
+ " error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void migrateFavicons(SQLiteDatabase db) {
|
||||
Cursor cursor = null;
|
||||
protected void migrateFavicons(SQLiteBridge db) {
|
||||
try {
|
||||
cursor = db.rawQuery(faviconQuery,
|
||||
new String[] {});
|
||||
if (cursor.getCount() > 0) {
|
||||
final int urlCol =
|
||||
cursor.getColumnIndexOrThrow(faviconUrl);
|
||||
final int dataCol =
|
||||
cursor.getColumnIndexOrThrow(faviconData);
|
||||
final int mimeCol =
|
||||
cursor.getColumnIndexOrThrow(faviconMime);
|
||||
ArrayList<Object[]> queryResult = db.query(faviconQuery);
|
||||
final int urlCol = db.getColumnIndex(faviconUrl);
|
||||
final int mimeCol = db.getColumnIndex(faviconMime);
|
||||
final int dataCol = db.getColumnIndex(faviconData);
|
||||
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
String url = cursor.getString(urlCol);
|
||||
String mime = cursor.getString(mimeCol);
|
||||
byte[] data = cursor.getBlob(dataCol);
|
||||
addFavicon(url, mime, data);
|
||||
cursor.moveToNext();
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
} catch (SQLiteException e) {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
for (Object[] resultRow: queryResult) {
|
||||
String url = (String)resultRow[urlCol];
|
||||
String mime = (String)resultRow[mimeCol];
|
||||
ByteBuffer dataBuff = (ByteBuffer)resultRow[dataCol];
|
||||
addFavicon(url, mime, dataBuff);
|
||||
}
|
||||
} catch (SQLiteBridgeException e) {
|
||||
Log.i(LOGTAG, "Failed to get favicons: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SQLiteDatabase openPlaces(String dbPath) throws SQLiteException {
|
||||
/* http://stackoverflow.com/questions/2528489/no-such-table-android-metadata-whats-the-problem */
|
||||
SQLiteDatabase db = SQLiteDatabase.openDatabase(dbPath,
|
||||
null,
|
||||
SQLiteDatabase.OPEN_READONLY |
|
||||
SQLiteDatabase.NO_LOCALIZED_COLLATORS);
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
protected void migratePlaces(File aFile) {
|
||||
String dbPath = aFile.getPath() + "/places.sqlite";
|
||||
String dbPathWal = aFile.getPath() + "/places.sqlite-wal";
|
||||
@ -329,9 +274,9 @@ public class ProfileMigrator {
|
||||
File dbFileWal = new File(dbPathWal);
|
||||
File dbFileShm = new File(dbPathShm);
|
||||
|
||||
SQLiteDatabase db = null;
|
||||
SQLiteBridge db = null;
|
||||
try {
|
||||
db = openPlaces(dbPath);
|
||||
db = new SQLiteBridge(dbPath);
|
||||
migrateBookmarks(db);
|
||||
migrateHistory(db);
|
||||
migrateFavicons(db);
|
||||
@ -343,7 +288,7 @@ public class ProfileMigrator {
|
||||
dbFileShm.delete();
|
||||
|
||||
Log.i(LOGTAG, "Profile migration finished");
|
||||
} catch (SQLiteException e) {
|
||||
} catch (SQLiteBridgeException e) {
|
||||
if (db != null) {
|
||||
db.close();
|
||||
}
|
||||
|
@ -63,13 +63,9 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
|
||||
private static final Uri BOOKMARKS_CONTENT_URI_POST_11 = Uri.parse("content://com.android.browser/bookmarks");
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
Cursor c = cr.query(Browser.BOOKMARKS_URI,
|
||||
new String[] { URL_COLUMN_ID,
|
||||
BookmarkColumns.URL,
|
||||
BookmarkColumns.TITLE,
|
||||
BookmarkColumns.FAVICON,
|
||||
URL_COLUMN_THUMBNAIL },
|
||||
projection,
|
||||
// The length restriction on URL is for the same reason as in the general bookmark query
|
||||
// (see comment earlier in this file).
|
||||
(urlFilter != null ? "(" + Browser.BookmarkColumns.URL + " NOT LIKE ? ) AND " : "" ) +
|
||||
@ -86,6 +82,28 @@ public class AndroidBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
return new AndroidDBCursor(c);
|
||||
}
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { URL_COLUMN_ID,
|
||||
BookmarkColumns.URL,
|
||||
BookmarkColumns.TITLE,
|
||||
BookmarkColumns.FAVICON },
|
||||
constraint,
|
||||
limit,
|
||||
null);
|
||||
}
|
||||
|
||||
public Cursor getTopSites(ContentResolver cr, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { URL_COLUMN_ID,
|
||||
BookmarkColumns.URL,
|
||||
BookmarkColumns.TITLE,
|
||||
URL_COLUMN_THUMBNAIL },
|
||||
"",
|
||||
limit,
|
||||
BrowserDB.ABOUT_PAGES_URL_FILTER);
|
||||
}
|
||||
|
||||
public void updateVisitedHistory(ContentResolver cr, String uri) {
|
||||
Browser.updateVisitedHistory(cr, uri, true);
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ import android.database.Cursor;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
|
||||
public class BrowserDB {
|
||||
public static String ABOUT_PAGES_URL_FILTER = "about:%";
|
||||
|
||||
public static interface URLColumns {
|
||||
public static String URL = "url";
|
||||
public static String TITLE = "title";
|
||||
@ -53,7 +55,9 @@ public class BrowserDB {
|
||||
private static BrowserDBIface sDb;
|
||||
|
||||
public interface BrowserDBIface {
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter);
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit);
|
||||
|
||||
public Cursor getTopSites(ContentResolver cr, int limit);
|
||||
|
||||
public void updateVisitedHistory(ContentResolver cr, String uri);
|
||||
|
||||
@ -87,12 +91,12 @@ public class BrowserDB {
|
||||
sDb = new LocalBrowserDB(BrowserContract.DEFAULT_PROFILE);
|
||||
}
|
||||
|
||||
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
return sDb.filter(cr, constraint, limit, urlFilter);
|
||||
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return sDb.filter(cr, constraint, limit);
|
||||
}
|
||||
|
||||
public static Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return sDb.filter(cr, constraint, limit, null);
|
||||
public static Cursor getTopSites(ContentResolver cr, int limit) {
|
||||
return sDb.getTopSites(cr, limit);
|
||||
}
|
||||
|
||||
public static void updateVisitedHistory(ContentResolver cr, String uri) {
|
||||
|
@ -80,13 +80,9 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
return uri.buildUpon().appendQueryParameter(BrowserContract.PARAM_PROFILE, mProfile).build();
|
||||
}
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint, int limit, CharSequence urlFilter) {
|
||||
Cursor c = cr.query(appendProfileAndLimit(History.CONTENT_URI, limit),
|
||||
new String[] { History._ID,
|
||||
History.URL,
|
||||
History.TITLE,
|
||||
History.FAVICON,
|
||||
History.THUMBNAIL },
|
||||
projection,
|
||||
(urlFilter != null ? "(" + History.URL + " NOT LIKE ? ) AND " : "" ) +
|
||||
"(" + History.URL + " LIKE ? OR " + History.TITLE + " LIKE ?)",
|
||||
urlFilter == null ? new String[] {"%" + constraint.toString() + "%", "%" + constraint.toString() + "%"} :
|
||||
@ -100,6 +96,28 @@ public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
|
||||
return new LocalDBCursor(c);
|
||||
}
|
||||
|
||||
public Cursor filter(ContentResolver cr, CharSequence constraint, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { History._ID,
|
||||
History.URL,
|
||||
History.TITLE,
|
||||
History.FAVICON },
|
||||
constraint,
|
||||
limit,
|
||||
null);
|
||||
}
|
||||
|
||||
public Cursor getTopSites(ContentResolver cr, int limit) {
|
||||
return filterAllSites(cr,
|
||||
new String[] { History._ID,
|
||||
History.URL,
|
||||
History.TITLE,
|
||||
History.THUMBNAIL },
|
||||
"",
|
||||
limit,
|
||||
BrowserDB.ABOUT_PAGES_URL_FILTER);
|
||||
}
|
||||
|
||||
private void truncateHistory(ContentResolver cr) {
|
||||
Cursor cursor = null;
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
android:paddingLeft="15dip"
|
||||
android:paddingRight="40dip"
|
||||
android:hint="@string/awesomebar_default_text"
|
||||
android:inputType="textUri"
|
||||
android:inputType="textUri|textNoSuggestions"
|
||||
android:imeOptions="actionSearch"
|
||||
android:singleLine="true"
|
||||
android:gravity="center_vertical|left">
|
||||
|
71
mobile/android/base/sqlite/ByteBufferInputStream.java
Normal file
71
mobile/android/base/sqlite/ByteBufferInputStream.java
Normal file
@ -0,0 +1,71 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Gian-Carlo Pascutto <gpascutto@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko.sqlite;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/*
|
||||
* Helper class to make the ByteBuffers returned by SQLite BLOB
|
||||
* easier to use.
|
||||
*/
|
||||
public class ByteBufferInputStream extends InputStream {
|
||||
private ByteBuffer mByteBuffer;
|
||||
|
||||
public ByteBufferInputStream(ByteBuffer aByteBuffer) {
|
||||
mByteBuffer = aByteBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read() throws IOException {
|
||||
if (!mByteBuffer.hasRemaining()) {
|
||||
return -1;
|
||||
}
|
||||
return mByteBuffer.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read(byte[] aBytes, int aOffset, int aLen)
|
||||
throws IOException {
|
||||
int toRead = Math.min(aLen, mByteBuffer.remaining());
|
||||
mByteBuffer.get(aBytes, aOffset, toRead);
|
||||
return toRead;
|
||||
}
|
||||
}
|
101
mobile/android/base/sqlite/SQLiteBridge.java
Normal file
101
mobile/android/base/sqlite/SQLiteBridge.java
Normal file
@ -0,0 +1,101 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Gian-Carlo Pascutto <gpascutto@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko.sqlite;
|
||||
|
||||
import org.mozilla.gecko.sqlite.SQLiteBridgeException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/*
|
||||
* This class allows using the mozsqlite3 library included with Firefox
|
||||
* to read SQLite databases, instead of the Android SQLiteDataBase API,
|
||||
* which might use whatever outdated DB is present on the Android system.
|
||||
*/
|
||||
public class SQLiteBridge {
|
||||
private static final String LOGTAG = "SQLiteBridge";
|
||||
// Path to the database. We reopen it every query.
|
||||
private String mDb;
|
||||
// Remember column names from last query result.
|
||||
private ArrayList<String> mColumns;
|
||||
|
||||
// JNI code in $(topdir)/mozglue/android/..
|
||||
private static native void sqliteCall(String aDb, String aQuery,
|
||||
String[] aParams,
|
||||
ArrayList<String> aColumns,
|
||||
ArrayList<Object[]> aRes)
|
||||
throws SQLiteBridgeException;
|
||||
|
||||
// Takes the path to the database we want to access.
|
||||
public SQLiteBridge(String aDb) throws SQLiteBridgeException {
|
||||
mDb = aDb;
|
||||
}
|
||||
|
||||
// Do an SQL query without parameters
|
||||
public ArrayList<Object[]> query(String aQuery) throws SQLiteBridgeException {
|
||||
String[] params = new String[0];
|
||||
return query(aQuery, params);
|
||||
}
|
||||
|
||||
// Do an SQL query, substituting the parameters in the query with the passed
|
||||
// parameters. The parameters are subsituded in order, so named parameters
|
||||
// are not supported.
|
||||
// The result is returned as an ArrayList<Object[]>, with each
|
||||
// row being an entry in the ArrayList, and each column being one Object
|
||||
// in the Object[] array. The columns are of type null,
|
||||
// direct ByteBuffer (BLOB), or String (everything else).
|
||||
public ArrayList<Object[]> query(String aQuery, String[] aParams)
|
||||
throws SQLiteBridgeException {
|
||||
ArrayList<Object[]> result = new ArrayList<Object[]>();
|
||||
mColumns = new ArrayList<String>();
|
||||
sqliteCall(mDb, aQuery, aParams, mColumns, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Gets the index in the row Object[] for the given column name.
|
||||
// Returns -1 if not found.
|
||||
public int getColumnIndex(String aColumnName) {
|
||||
return mColumns.lastIndexOf(aColumnName);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
// nop, provided for API compatibility with SQLiteDatabase.
|
||||
}
|
||||
}
|
47
mobile/android/base/sqlite/SQLiteBridgeException.java
Normal file
47
mobile/android/base/sqlite/SQLiteBridgeException.java
Normal file
@ -0,0 +1,47 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Gian-Carlo Pascutto <gpascutto@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
package org.mozilla.gecko.sqlite;
|
||||
|
||||
public class SQLiteBridgeException extends Exception {
|
||||
static final long serialVersionUID = 1L;
|
||||
|
||||
public SQLiteBridgeException() {}
|
||||
public SQLiteBridgeException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -426,6 +426,12 @@ var BrowserApp = {
|
||||
let referrerURI = "referrerURI" in aParams ? aParams.referrerURI : null;
|
||||
let charset = "charset" in aParams ? aParams.charset : null;
|
||||
|
||||
if ("showProgress" in aParams) {
|
||||
let tab = this.getTabForBrowser(aBrowser);
|
||||
if (tab)
|
||||
tab.showProgress = aParams.showProgress;
|
||||
}
|
||||
|
||||
try {
|
||||
aBrowser.loadURIWithFlags(aURI, flags, referrerURI, charset, postData);
|
||||
} catch(e) {
|
||||
@ -825,6 +831,11 @@ var BrowserApp = {
|
||||
};
|
||||
|
||||
let url = this.getSearchOrFixupURI(data);
|
||||
|
||||
// Don't show progress throbber for about:home
|
||||
if (url == "about:home")
|
||||
params.showProgress = false;
|
||||
|
||||
if (aTopic == "Tab:Add")
|
||||
this.addTab(url, params);
|
||||
else
|
||||
@ -1297,6 +1308,7 @@ function Tab(aURL, aParams) {
|
||||
this.browser = null;
|
||||
this.vbox = null;
|
||||
this.id = 0;
|
||||
this.showProgress = true;
|
||||
this.create(aURL, aParams);
|
||||
this._viewport = { x: 0, y: 0, width: gScreenWidth, height: gScreenHeight, offsetX: 0, offsetY: 0,
|
||||
pageWidth: gScreenWidth, pageHeight: gScreenHeight, zoom: 1.0 };
|
||||
@ -1368,6 +1380,9 @@ Tab.prototype = {
|
||||
let referrerURI = "referrerURI" in aParams ? aParams.referrerURI : null;
|
||||
let charset = "charset" in aParams ? aParams.charset : null;
|
||||
|
||||
// This determines whether or not we show the progress throbber in the urlbar
|
||||
this.showProgress = "showProgress" in aParams ? aParams.showProgress : true;
|
||||
|
||||
try {
|
||||
this.browser.loadURIWithFlags(aURL, flags, referrerURI, charset, postData);
|
||||
} catch(e) {
|
||||
@ -1749,11 +1764,14 @@ Tab.prototype = {
|
||||
type: "Content:StateChange",
|
||||
tabID: this.id,
|
||||
uri: uri,
|
||||
state: aStateFlags
|
||||
state: aStateFlags,
|
||||
showProgress: this.showProgress
|
||||
}
|
||||
};
|
||||
|
||||
sendMessageToJava(message);
|
||||
|
||||
// Reset showProgress after state change
|
||||
this.showProgress = true;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -62,6 +62,8 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include "Zip.h"
|
||||
#include "sqlite3.h"
|
||||
#include "SQLiteBridge.h"
|
||||
|
||||
/* Android headers don't define RUSAGE_THREAD */
|
||||
#ifndef RUSAGE_THREAD
|
||||
@ -284,23 +286,24 @@ SHELL_WRAPPER1(onChangeNetworkLinkStatus, jstring)
|
||||
SHELL_WRAPPER1(reportJavaCrash, jstring)
|
||||
SHELL_WRAPPER0(executeNextRunnable)
|
||||
SHELL_WRAPPER1(cameraCallbackBridge, jbyteArray)
|
||||
SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble);
|
||||
SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong);
|
||||
SHELL_WRAPPER0(bindWidgetTexture);
|
||||
SHELL_WRAPPER3_WITH_RETURN(saveMessageInSentbox, jint, jstring, jstring, jlong);
|
||||
SHELL_WRAPPER6(notifySmsSent, jint, jstring, jstring, jlong, jint, jlong);
|
||||
SHELL_WRAPPER4(notifySmsDelivered, jint, jstring, jstring, jlong);
|
||||
SHELL_WRAPPER3(notifySmsSendFailed, jint, jint, jlong);
|
||||
SHELL_WRAPPER7(notifyGetSms, jint, jstring, jstring, jstring, jlong, jint, jlong);
|
||||
SHELL_WRAPPER3(notifyGetSmsFailed, jint, jint, jlong);
|
||||
SHELL_WRAPPER3(notifySmsDeleted, jboolean, jint, jlong);
|
||||
SHELL_WRAPPER3(notifySmsDeleteFailed, jint, jint, jlong);
|
||||
SHELL_WRAPPER2(notifyNoMessageInList, jint, jlong);
|
||||
SHELL_WRAPPER8(notifyListCreated, jint, jint, jstring, jstring, jstring, jlong, jint, jlong);
|
||||
SHELL_WRAPPER7(notifyGotNextMessage, jint, jstring, jstring, jstring, jlong, jint, jlong);
|
||||
SHELL_WRAPPER3(notifyReadingMessageListFailed, jint, jint, jlong);
|
||||
SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble)
|
||||
SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong)
|
||||
SHELL_WRAPPER0(bindWidgetTexture)
|
||||
SHELL_WRAPPER3_WITH_RETURN(saveMessageInSentbox, jint, jstring, jstring, jlong)
|
||||
SHELL_WRAPPER6(notifySmsSent, jint, jstring, jstring, jlong, jint, jlong)
|
||||
SHELL_WRAPPER4(notifySmsDelivered, jint, jstring, jstring, jlong)
|
||||
SHELL_WRAPPER3(notifySmsSendFailed, jint, jint, jlong)
|
||||
SHELL_WRAPPER7(notifyGetSms, jint, jstring, jstring, jstring, jlong, jint, jlong)
|
||||
SHELL_WRAPPER3(notifyGetSmsFailed, jint, jint, jlong)
|
||||
SHELL_WRAPPER3(notifySmsDeleted, jboolean, jint, jlong)
|
||||
SHELL_WRAPPER3(notifySmsDeleteFailed, jint, jint, jlong)
|
||||
SHELL_WRAPPER2(notifyNoMessageInList, jint, jlong)
|
||||
SHELL_WRAPPER8(notifyListCreated, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
|
||||
SHELL_WRAPPER7(notifyGotNextMessage, jint, jstring, jstring, jstring, jlong, jint, jlong)
|
||||
SHELL_WRAPPER3(notifyReadingMessageListFailed, jint, jint, jlong)
|
||||
|
||||
static void * xul_handle = NULL;
|
||||
static void * sqlite_handle = NULL;
|
||||
static time_t apk_mtime = 0;
|
||||
#ifdef DEBUG
|
||||
extern "C" int extractLibs = 1;
|
||||
@ -618,12 +621,10 @@ report_mapping(char *name, void *base, uint32_t len, uint32_t offset)
|
||||
extern "C" void simple_linker_init(void);
|
||||
|
||||
static void
|
||||
loadLibs(const char *apkName)
|
||||
loadGeckoLibs(const char *apkName)
|
||||
{
|
||||
chdir(getenv("GRE_HOME"));
|
||||
|
||||
simple_linker_init();
|
||||
|
||||
struct stat status;
|
||||
if (!stat(apkName, &status))
|
||||
apk_mtime = status.st_mtime;
|
||||
@ -635,7 +636,6 @@ loadLibs(const char *apkName)
|
||||
|
||||
Zip *zip = new Zip(apkName);
|
||||
|
||||
lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
file_ids = (char *)extractBuf("lib.id", zip);
|
||||
#endif
|
||||
@ -645,7 +645,6 @@ loadLibs(const char *apkName)
|
||||
MOZLOAD("nspr4");
|
||||
MOZLOAD("plc4");
|
||||
MOZLOAD("plds4");
|
||||
MOZLOAD("mozsqlite3");
|
||||
MOZLOAD("nssutil3");
|
||||
MOZLOAD("nss3");
|
||||
MOZLOAD("ssl3");
|
||||
@ -712,20 +711,67 @@ loadLibs(const char *apkName)
|
||||
StartupTimeline_Record(LIBRARIES_LOADED, &t1);
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_loadLibs(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName, jboolean jShouldExtract)
|
||||
static void loadSQLiteLibs(const char *apkName)
|
||||
{
|
||||
if (jShouldExtract)
|
||||
extractLibs = 1;
|
||||
chdir(getenv("GRE_HOME"));
|
||||
|
||||
simple_linker_init();
|
||||
|
||||
struct stat status;
|
||||
if (!stat(apkName, &status))
|
||||
apk_mtime = status.st_mtime;
|
||||
|
||||
Zip *zip = new Zip(apkName);
|
||||
lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
file_ids = (char *)extractBuf("lib.id", zip);
|
||||
#endif
|
||||
|
||||
#define MOZLOAD(name) mozload("lib" name ".so", zip)
|
||||
sqlite_handle = MOZLOAD("mozsqlite3");
|
||||
#undef MOZLOAD
|
||||
|
||||
delete zip;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
free(file_ids);
|
||||
file_ids = NULL;
|
||||
#endif
|
||||
|
||||
if (!sqlite_handle)
|
||||
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libmozsqlite3!");
|
||||
|
||||
setup_sqlite_functions(sqlite_handle);
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_loadGeckoLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName)
|
||||
{
|
||||
const char* str;
|
||||
// XXX: java doesn't give us true UTF8, we should figure out something
|
||||
// XXX: java doesn't give us true UTF8, we should figure out something
|
||||
// better to do here
|
||||
str = jenv->GetStringUTFChars(jApkName, NULL);
|
||||
if (str == NULL)
|
||||
return;
|
||||
|
||||
loadLibs(str);
|
||||
loadGeckoLibs(str);
|
||||
jenv->ReleaseStringUTFChars(jApkName, str);
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_GeckoAppShell_loadSQLiteLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName, jboolean jShouldExtract) {
|
||||
if (jShouldExtract)
|
||||
extractLibs = 1;
|
||||
|
||||
const char* str;
|
||||
// XXX: java doesn't give us true UTF8, we should figure out something
|
||||
// better to do here
|
||||
str = jenv->GetStringUTFChars(jApkName, NULL);
|
||||
if (str == NULL)
|
||||
return;
|
||||
|
||||
loadSQLiteLibs(str);
|
||||
jenv->ReleaseStringUTFChars(jApkName, str);
|
||||
}
|
||||
|
||||
@ -745,7 +791,8 @@ ChildProcessInit(int argc, char* argv[])
|
||||
}
|
||||
|
||||
fillLibCache(argv[argc - 1]);
|
||||
loadLibs(argv[i]);
|
||||
loadSQLiteLibs(argv[i]);
|
||||
loadGeckoLibs(argv[i]);
|
||||
|
||||
// don't pass the last arg - it's only recognized by the lib cache
|
||||
argc--;
|
||||
|
@ -53,10 +53,12 @@ DEFINES += \
|
||||
CPPSRCS = \
|
||||
nsGeckoUtils.cpp \
|
||||
APKOpen.cpp \
|
||||
SQLiteBridge.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../linker
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/startup
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/db/sqlite3/src
|
||||
ifdef MOZ_OLD_LINKER
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/other-licenses/android
|
||||
ifeq ($(CPU_ARCH),arm)
|
||||
|
312
mozglue/android/SQLiteBridge.cpp
Normal file
312
mozglue/android/SQLiteBridge.cpp
Normal file
@ -0,0 +1,312 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Gian-Carlo Pascutto <gpascutto@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include "dlfcn.h"
|
||||
#include "APKOpen.h"
|
||||
#include "SQLiteBridge.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(x...) __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", x)
|
||||
#else
|
||||
#define LOG(x...)
|
||||
#endif
|
||||
|
||||
#define SQLITE_WRAPPER_INT(name) name ## _t f_ ## name;
|
||||
|
||||
SQLITE_WRAPPER_INT(sqlite3_open)
|
||||
SQLITE_WRAPPER_INT(sqlite3_errmsg)
|
||||
SQLITE_WRAPPER_INT(sqlite3_prepare_v2)
|
||||
SQLITE_WRAPPER_INT(sqlite3_bind_parameter_count)
|
||||
SQLITE_WRAPPER_INT(sqlite3_bind_text)
|
||||
SQLITE_WRAPPER_INT(sqlite3_step)
|
||||
SQLITE_WRAPPER_INT(sqlite3_column_count)
|
||||
SQLITE_WRAPPER_INT(sqlite3_finalize)
|
||||
SQLITE_WRAPPER_INT(sqlite3_close)
|
||||
SQLITE_WRAPPER_INT(sqlite3_column_name)
|
||||
SQLITE_WRAPPER_INT(sqlite3_column_type)
|
||||
SQLITE_WRAPPER_INT(sqlite3_column_blob)
|
||||
SQLITE_WRAPPER_INT(sqlite3_column_bytes)
|
||||
SQLITE_WRAPPER_INT(sqlite3_column_text)
|
||||
|
||||
void setup_sqlite_functions(void *sqlite_handle)
|
||||
{
|
||||
#define GETFUNC(name) f_ ## name = (name ## _t) __wrap_dlsym(sqlite_handle, #name)
|
||||
GETFUNC(sqlite3_open);
|
||||
GETFUNC(sqlite3_errmsg);
|
||||
GETFUNC(sqlite3_prepare_v2);
|
||||
GETFUNC(sqlite3_bind_parameter_count);
|
||||
GETFUNC(sqlite3_bind_text);
|
||||
GETFUNC(sqlite3_step);
|
||||
GETFUNC(sqlite3_column_count);
|
||||
GETFUNC(sqlite3_finalize);
|
||||
GETFUNC(sqlite3_close);
|
||||
GETFUNC(sqlite3_column_name);
|
||||
GETFUNC(sqlite3_column_type);
|
||||
GETFUNC(sqlite3_column_blob);
|
||||
GETFUNC(sqlite3_column_bytes);
|
||||
GETFUNC(sqlite3_column_text);
|
||||
#undef GETFUNC
|
||||
}
|
||||
|
||||
static bool initialized = false;
|
||||
static jclass stringClass;
|
||||
static jclass objectClass;
|
||||
static jclass byteBufferClass;
|
||||
static jclass arrayListClass;
|
||||
static jmethodID jByteBufferAllocateDirect;
|
||||
static jmethodID jArrayListAdd;
|
||||
static jobject jNull;
|
||||
|
||||
static void
|
||||
JNI_Throw(JNIEnv* jenv, const char* name, const char* msg)
|
||||
{
|
||||
jclass cls = jenv->FindClass(name);
|
||||
if (cls == NULL) {
|
||||
LOG("Couldn't find exception class (or exception pending)\n");
|
||||
return;
|
||||
}
|
||||
int rc = jenv->ThrowNew(cls, msg);
|
||||
if (rc < 0) {
|
||||
LOG("Error throwing exception\n");
|
||||
}
|
||||
jenv->DeleteLocalRef(cls);
|
||||
}
|
||||
|
||||
static void
|
||||
JNI_Setup(JNIEnv* jenv)
|
||||
{
|
||||
if (initialized) return;
|
||||
|
||||
objectClass = jenv->FindClass("java/lang/Object");
|
||||
stringClass = jenv->FindClass("java/lang/String");
|
||||
byteBufferClass = jenv->FindClass("java/nio/ByteBuffer");
|
||||
arrayListClass = jenv->FindClass("java/util/ArrayList");
|
||||
jNull = jenv->NewGlobalRef(NULL);
|
||||
|
||||
if (stringClass == NULL || objectClass == NULL
|
||||
|| byteBufferClass == NULL || arrayListClass == NULL) {
|
||||
LOG("Error finding classes");
|
||||
JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException",
|
||||
"FindClass error");
|
||||
return;
|
||||
}
|
||||
|
||||
// public static ByteBuffer allocateDirect(int capacity)
|
||||
jByteBufferAllocateDirect =
|
||||
jenv->GetStaticMethodID(byteBufferClass, "allocateDirect", "(I)Ljava/nio/ByteBuffer;");
|
||||
// boolean add(Object o)
|
||||
jArrayListAdd =
|
||||
jenv->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
if (jByteBufferAllocateDirect == NULL || jArrayListAdd == NULL) {
|
||||
LOG("Error finding methods");
|
||||
JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException",
|
||||
"GetMethodId error");
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass,
|
||||
jstring jDb,
|
||||
jstring jQuery,
|
||||
jobjectArray jParams,
|
||||
jobject jColumns,
|
||||
jobject jArrayList)
|
||||
{
|
||||
JNI_Setup(jenv);
|
||||
|
||||
const char* queryStr;
|
||||
queryStr = jenv->GetStringUTFChars(jQuery, NULL);
|
||||
|
||||
const char* dbPath;
|
||||
dbPath = jenv->GetStringUTFChars(jDb, NULL);
|
||||
|
||||
const char *pzTail;
|
||||
sqlite3_stmt *ppStmt;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
rc = f_sqlite3_open(dbPath, &db);
|
||||
jenv->ReleaseStringUTFChars(jDb, dbPath);
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
LOG("Can't open database: %s\n", f_sqlite3_errmsg(db));
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
rc = f_sqlite3_prepare_v2(db, queryStr, -1, &ppStmt, &pzTail);
|
||||
if (rc != SQLITE_OK || ppStmt == NULL) {
|
||||
LOG("Can't prepare statement: %s\n", f_sqlite3_errmsg(db));
|
||||
goto error_close;
|
||||
}
|
||||
jenv->ReleaseStringUTFChars(jQuery, queryStr);
|
||||
|
||||
// Check if number of parameters matches
|
||||
jsize numPars;
|
||||
numPars = jenv->GetArrayLength(jParams);
|
||||
int sqlNumPars;
|
||||
sqlNumPars = f_sqlite3_bind_parameter_count(ppStmt);
|
||||
if (numPars != sqlNumPars) {
|
||||
LOG("Passed parameter count (%d) doesn't match SQL parameter count (%d)\n",
|
||||
numPars, sqlNumPars);
|
||||
goto error_close;
|
||||
}
|
||||
// Bind parameters, if any
|
||||
if (numPars > 0) {
|
||||
for (int i = 0; i < numPars; i++) {
|
||||
jobject jObjectParam = jenv->GetObjectArrayElement(jParams, i);
|
||||
// IsInstanceOf or isAssignableFrom? String is final, so IsInstanceOf
|
||||
// should be OK.
|
||||
jboolean isString = jenv->IsInstanceOf(jObjectParam, stringClass);
|
||||
if (isString != JNI_TRUE) {
|
||||
LOG("Parameter is not of String type");
|
||||
goto error_close;
|
||||
}
|
||||
jstring jStringParam = (jstring)jObjectParam;
|
||||
const char* paramStr = jenv->GetStringUTFChars(jStringParam, NULL);
|
||||
// SQLite parameters index from 1.
|
||||
rc = f_sqlite3_bind_text(ppStmt, i + 1, paramStr, -1, SQLITE_TRANSIENT);
|
||||
jenv->ReleaseStringUTFChars(jStringParam, paramStr);
|
||||
if (rc != SQLITE_OK) {
|
||||
LOG("Error binding query parameter");
|
||||
goto error_close;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the query and step through the results
|
||||
rc = f_sqlite3_step(ppStmt);
|
||||
if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
|
||||
LOG("Can't step statement: (%d) %s\n", rc, f_sqlite3_errmsg(db));
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Get the column names
|
||||
int cols;
|
||||
cols = f_sqlite3_column_count(ppStmt);
|
||||
for (int i = 0; i < cols; i++) {
|
||||
const char* colName = f_sqlite3_column_name(ppStmt, i);
|
||||
jstring jStr = jenv->NewStringUTF(colName);
|
||||
jenv->CallBooleanMethod(jColumns, jArrayListAdd, jStr);
|
||||
jenv->DeleteLocalRef(jStr);
|
||||
}
|
||||
|
||||
// For each row, add an Object[] to the passed ArrayList,
|
||||
// with that containing either String or ByteArray objects
|
||||
// containing the columns
|
||||
do {
|
||||
// Process row
|
||||
// Construct Object[]
|
||||
jobjectArray jRow = jenv->NewObjectArray(cols,
|
||||
objectClass,
|
||||
NULL);
|
||||
if (jRow == NULL) {
|
||||
LOG("Can't allocate jRow Object[]\n");
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cols; i++) {
|
||||
int colType = f_sqlite3_column_type(ppStmt, i);
|
||||
if (colType == SQLITE_BLOB) {
|
||||
// Treat as blob
|
||||
const void* blob = f_sqlite3_column_blob(ppStmt, i);
|
||||
int colLen = f_sqlite3_column_bytes(ppStmt, i);
|
||||
|
||||
// Construct ByteBuffer of correct size
|
||||
jobject jByteBuffer =
|
||||
jenv->CallStaticObjectMethod(byteBufferClass,
|
||||
jByteBufferAllocateDirect,
|
||||
colLen);
|
||||
if (jByteBuffer == NULL) {
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
// Get its backing array
|
||||
void* bufferArray = jenv->GetDirectBufferAddress(jByteBuffer);
|
||||
if (bufferArray == NULL) {
|
||||
LOG("Failure calling GetDirectBufferAddress\n");
|
||||
goto error_close;
|
||||
}
|
||||
memcpy(bufferArray, blob, colLen);
|
||||
|
||||
jenv->SetObjectArrayElement(jRow, i, jByteBuffer);
|
||||
jenv->DeleteLocalRef(jByteBuffer);
|
||||
} else if (colType == SQLITE_NULL) {
|
||||
jenv->SetObjectArrayElement(jRow, i, jNull);
|
||||
} else {
|
||||
// Treat everything else as text
|
||||
const char* txt = (const char*)f_sqlite3_column_text(ppStmt, i);
|
||||
jstring jStr = jenv->NewStringUTF(txt);
|
||||
jenv->SetObjectArrayElement(jRow, i, jStr);
|
||||
jenv->DeleteLocalRef(jStr);
|
||||
}
|
||||
}
|
||||
|
||||
// Append Object[] to ArrayList<Object[]>
|
||||
// JNI doesn't know about the generic, so use Object[] as Object
|
||||
jenv->CallBooleanMethod(jArrayList, jArrayListAdd, jRow);
|
||||
|
||||
// Clean up
|
||||
jenv->DeleteLocalRef(jRow);
|
||||
|
||||
// Get next row
|
||||
rc = f_sqlite3_step(ppStmt);
|
||||
// Real error?
|
||||
if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
|
||||
LOG("Can't re-step statement:(%d) %s\n", rc, f_sqlite3_errmsg(db));
|
||||
goto error_close;
|
||||
}
|
||||
} while (rc != SQLITE_DONE);
|
||||
|
||||
rc = f_sqlite3_finalize(ppStmt);
|
||||
if (rc != SQLITE_OK) {
|
||||
LOG("Can't finalize statement: %s\n", f_sqlite3_errmsg(db));
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
f_sqlite3_close(db);
|
||||
return;
|
||||
|
||||
error_close:
|
||||
f_sqlite3_close(db);
|
||||
JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", "SQLite error");
|
||||
return;
|
||||
}
|
63
mozglue/android/SQLiteBridge.h
Normal file
63
mozglue/android/SQLiteBridge.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Android code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Gian-Carlo Pascutto <gpascutto@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef SQLiteBridge_h
|
||||
#define SQLiteBridge_h
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
void setup_sqlite_functions(void *sqlite_handle);
|
||||
|
||||
#define SQLITE_WRAPPER(name, return_type, args...) \
|
||||
typedef return_type (*name ## _t)(args); \
|
||||
extern name ## _t f_ ## name;
|
||||
|
||||
SQLITE_WRAPPER(sqlite3_open, int, const char*, sqlite3**)
|
||||
SQLITE_WRAPPER(sqlite3_errmsg, const char*, sqlite3*)
|
||||
SQLITE_WRAPPER(sqlite3_prepare_v2, int, sqlite3*, const char*, int, sqlite3_stmt**, const char**)
|
||||
SQLITE_WRAPPER(sqlite3_bind_parameter_count, int, sqlite3_stmt*)
|
||||
SQLITE_WRAPPER(sqlite3_bind_text, int, sqlite3_stmt*, int, const char*, int, void(*)(void*))
|
||||
SQLITE_WRAPPER(sqlite3_step, int, sqlite3_stmt*)
|
||||
SQLITE_WRAPPER(sqlite3_column_count, int, sqlite3_stmt*)
|
||||
SQLITE_WRAPPER(sqlite3_finalize, int, sqlite3_stmt*)
|
||||
SQLITE_WRAPPER(sqlite3_close, int, sqlite3*)
|
||||
SQLITE_WRAPPER(sqlite3_column_name, const char*, sqlite3_stmt*, int)
|
||||
SQLITE_WRAPPER(sqlite3_column_type, int, sqlite3_stmt*, int)
|
||||
SQLITE_WRAPPER(sqlite3_column_blob, const void*, sqlite3_stmt*, int)
|
||||
SQLITE_WRAPPER(sqlite3_column_bytes, int, sqlite3_stmt*, int)
|
||||
SQLITE_WRAPPER(sqlite3_column_text, const unsigned char*, sqlite3_stmt*, int)
|
||||
|
||||
#endif /* SQLiteBridge_h */
|
@ -424,6 +424,7 @@ OS_LIBS += \
|
||||
-lui \
|
||||
-lmedia \
|
||||
-lhardware_legacy \
|
||||
-lhardware \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -48,9 +48,13 @@ LPCTSTR UACHelper::PrivsToDisable[] = {
|
||||
SE_ASSIGNPRIMARYTOKEN_NAME,
|
||||
SE_AUDIT_NAME,
|
||||
SE_BACKUP_NAME,
|
||||
// From testing ReadDirectoryChanges still succeeds even with a low
|
||||
// integrity process with the following privilege disabled.
|
||||
SE_CHANGE_NOTIFY_NAME,
|
||||
// CreateProcess will succeed but the app will fail to launch on some WinXP
|
||||
// machines if SE_CHANGE_NOTIFY_NAME is disabled. In particular this happens
|
||||
// for limited user accounts on those machines. The define is kept here as a
|
||||
// reminder that it should never be re-added.
|
||||
// This permission is for directory watching but also from MSDN: "This
|
||||
// privilege also causes the system to skip all traversal access checks."
|
||||
// SE_CHANGE_NOTIFY_NAME,
|
||||
SE_CREATE_GLOBAL_NAME,
|
||||
SE_CREATE_PAGEFILE_NAME,
|
||||
SE_CREATE_PERMANENT_NAME,
|
||||
|
@ -248,6 +248,77 @@ NS_IMETHODIMP nsOSHelperAppService::GetFromTypeAndExtension(const nsACString& aT
|
||||
return nsExternalHelperAppService::GetFromTypeAndExtension(aType, aFileExt, aMIMEInfo);
|
||||
}
|
||||
|
||||
// Returns the MIME types an application bundle explicitly claims to handle.
|
||||
// Returns NULL if aAppRef doesn't explicitly claim to handle any MIME types.
|
||||
// If the return value is non-NULL, the caller is responsible for freeing it.
|
||||
// This isn't necessarily the same as the MIME types the application bundle
|
||||
// is registered to handle in the Launch Services database. (For example
|
||||
// the Preview application is normally registered to handle the application/pdf
|
||||
// MIME type, even though it doesn't explicitly claim to handle *any* MIME
|
||||
// types in its Info.plist. This is probably because Preview does explicitly
|
||||
// claim to handle the com.adobe.pdf UTI, and Launch Services somehow
|
||||
// translates this into a claim to support the application/pdf MIME type.
|
||||
// Launch Services doesn't provide any APIs (documented or undocumented) to
|
||||
// query which MIME types a given application is registered to handle. So any
|
||||
// app that wants this information (e.g. the Default Apps pref pane) needs to
|
||||
// iterate through the entire Launch Services database -- a process which can
|
||||
// take several seconds.)
|
||||
static CFArrayRef GetMIMETypesHandledByApp(FSRef *aAppRef)
|
||||
{
|
||||
CFURLRef appURL = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aAppRef);
|
||||
if (!appURL) {
|
||||
return NULL;
|
||||
}
|
||||
CFDictionaryRef infoDict = ::CFBundleCopyInfoDictionaryForURL(appURL);
|
||||
::CFRelease(appURL);
|
||||
if (!infoDict) {
|
||||
return NULL;
|
||||
}
|
||||
CFTypeRef cfObject = ::CFDictionaryGetValue(infoDict, CFSTR("CFBundleDocumentTypes"));
|
||||
::CFRelease(infoDict);
|
||||
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFArrayGetTypeID())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFArrayRef docTypes = static_cast<CFArrayRef>(cfObject);
|
||||
CFIndex docTypesCount = ::CFArrayGetCount(docTypes);
|
||||
if (docTypesCount == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFMutableArrayRef mimeTypes =
|
||||
::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||
for (CFIndex i = 0; i < docTypesCount; ++i) {
|
||||
cfObject = ::CFArrayGetValueAtIndex(docTypes, i);
|
||||
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFDictionaryGetTypeID())) {
|
||||
continue;
|
||||
}
|
||||
CFDictionaryRef typeDict = static_cast<CFDictionaryRef>(cfObject);
|
||||
|
||||
// When this key is present (on OS X 10.5 and later), its contents
|
||||
// take precedence over CFBundleTypeMIMETypes (and CFBundleTypeExtensions
|
||||
// and CFBundleTypeOSTypes).
|
||||
cfObject = ::CFDictionaryGetValue(typeDict, CFSTR("LSItemContentTypes"));
|
||||
if (cfObject && (::CFGetTypeID(cfObject) == ::CFArrayGetTypeID())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cfObject = ::CFDictionaryGetValue(typeDict, CFSTR("CFBundleTypeMIMETypes"));
|
||||
if (!cfObject || (::CFGetTypeID(cfObject) != ::CFArrayGetTypeID())) {
|
||||
continue;
|
||||
}
|
||||
CFArrayRef mimeTypeHolder = static_cast<CFArrayRef>(cfObject);
|
||||
CFArrayAppendArray(mimeTypes, mimeTypeHolder,
|
||||
::CFRangeMake(0, ::CFArrayGetCount(mimeTypeHolder)));
|
||||
}
|
||||
|
||||
if (!::CFArrayGetCount(mimeTypes)) {
|
||||
::CFRelease(mimeTypes);
|
||||
mimeTypes = NULL;
|
||||
}
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
// aMIMEType and aFileExt might not match, If they don't we set *aFound to
|
||||
// false and return a minimal nsIMIMEInfo structure.
|
||||
already_AddRefed<nsIMIMEInfo>
|
||||
@ -281,22 +352,25 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
FSRef typeAppFSRef;
|
||||
FSRef extAppFSRef;
|
||||
|
||||
CFStringRef cfMIMEType = NULL;
|
||||
|
||||
if (!aMIMEType.IsEmpty()) {
|
||||
CFURLRef appURL = NULL;
|
||||
// CFStringCreateWithCString() can fail even if we're not out of memory --
|
||||
// for example if the 'cStr' parameter is something very wierd (like "ÿÿ~"
|
||||
// aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's
|
||||
// specified in the 'encoding' parameter. See bug 548719.
|
||||
CFStringRef CFType = ::CFStringCreateWithCString(NULL, flatType.get(), kCFStringEncodingUTF8);
|
||||
if (CFType) {
|
||||
err = ::LSCopyApplicationForMIMEType(CFType, kLSRolesAll, &appURL);
|
||||
cfMIMEType = ::CFStringCreateWithCString(NULL, flatType.get(),
|
||||
kCFStringEncodingUTF8);
|
||||
if (cfMIMEType) {
|
||||
err = ::LSCopyApplicationForMIMEType(cfMIMEType, kLSRolesAll, &appURL);
|
||||
if ((err == noErr) && appURL && ::CFURLGetFSRef(appURL, &typeAppFSRef)) {
|
||||
haveAppForType = true;
|
||||
PR_LOG(mLog, PR_LOG_DEBUG, ("LSCopyApplicationForMIMEType found a default application\n"));
|
||||
}
|
||||
if (appURL)
|
||||
if (appURL) {
|
||||
::CFRelease(appURL);
|
||||
::CFRelease(CFType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!aFileExt.IsEmpty()) {
|
||||
@ -304,15 +378,15 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
// for example if the 'cStr' parameter is something very wierd (like "ÿÿ~"
|
||||
// aka "\xFF\xFF~"), or possibly if it can't be interpreted as using what's
|
||||
// specified in the 'encoding' parameter. See bug 548719.
|
||||
CFStringRef CFExt = ::CFStringCreateWithCString(NULL, flatExt.get(), kCFStringEncodingUTF8);
|
||||
if (CFExt) {
|
||||
err = ::LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFExt,
|
||||
CFStringRef cfExt = ::CFStringCreateWithCString(NULL, flatExt.get(), kCFStringEncodingUTF8);
|
||||
if (cfExt) {
|
||||
err = ::LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, cfExt,
|
||||
kLSRolesAll, &extAppFSRef, nsnull);
|
||||
if (err == noErr) {
|
||||
haveAppForExt = true;
|
||||
PR_LOG(mLog, PR_LOG_DEBUG, ("LSGetApplicationForInfo found a default application\n"));
|
||||
}
|
||||
::CFRelease(CFExt);
|
||||
::CFRelease(cfExt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,13 +403,52 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
*aFound = true;
|
||||
}
|
||||
} else if (haveAppForExt) {
|
||||
// If aMIMEType isn't empty, it doesn't match aFileExt.
|
||||
// If aMIMEType isn't empty, it doesn't match aFileExt, which should mean
|
||||
// that we haven't found a matching app. But make an exception for an app
|
||||
// that also explicitly claims to handle aMIMEType, or which doesn't claim
|
||||
// to handle any MIME types. This helps work around the following Apple
|
||||
// design flaw:
|
||||
//
|
||||
// Launch Services is somewhat unreliable about registering Apple apps to
|
||||
// handle MIME types. Probably this is because Apple has officially
|
||||
// deprecated support for MIME types (in favor of UTIs). As a result,
|
||||
// most of Apple's own apps don't explicitly claim to handle any MIME
|
||||
// types (instead they claim to handle one or more UTIs). So Launch
|
||||
// Services must contain logic to translate support for a given UTI into
|
||||
// support for one or more MIME types, and it doesn't always do this
|
||||
// correctly. For example DiskImageMounter isn't (by default) registered
|
||||
// to handle the application/x-apple-diskimage MIME type. See bug 675356.
|
||||
//
|
||||
// Apple has also deprecated support for file extensions, and Apple apps
|
||||
// also don't register to handle them. But for some reason Launch Services
|
||||
// is (apparently) better about translating support for a given UTI into
|
||||
// support for one or more file extensions. It's not at all clear why.
|
||||
if (aMIMEType.IsEmpty()) {
|
||||
extAppIsDefault = true;
|
||||
*aFound = true;
|
||||
} else {
|
||||
CFArrayRef extAppMIMETypes = GetMIMETypesHandledByApp(&extAppFSRef);
|
||||
if (extAppMIMETypes) {
|
||||
if (cfMIMEType) {
|
||||
if (::CFArrayContainsValue(extAppMIMETypes,
|
||||
::CFRangeMake(0, ::CFArrayGetCount(extAppMIMETypes)),
|
||||
cfMIMEType)) {
|
||||
extAppIsDefault = true;
|
||||
*aFound = true;
|
||||
}
|
||||
}
|
||||
::CFRelease(extAppMIMETypes);
|
||||
} else {
|
||||
extAppIsDefault = true;
|
||||
*aFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cfMIMEType) {
|
||||
::CFRelease(cfMIMEType);
|
||||
}
|
||||
|
||||
if (aMIMEType.IsEmpty()) {
|
||||
if (haveAppForExt) {
|
||||
// If aMIMEType is empty and we've found a default app for aFileExt, try
|
||||
@ -382,26 +495,26 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
CFStringRef CFAppName = NULL;
|
||||
CFStringRef cfAppName = NULL;
|
||||
if (typeAppIsDefault) {
|
||||
app->InitWithFSRef(&typeAppFSRef);
|
||||
::LSCopyItemAttribute((const FSRef *) &typeAppFSRef, kLSRolesAll,
|
||||
kLSItemDisplayName, (CFTypeRef *) &CFAppName);
|
||||
kLSItemDisplayName, (CFTypeRef *) &cfAppName);
|
||||
} else {
|
||||
app->InitWithFSRef(&extAppFSRef);
|
||||
::LSCopyItemAttribute((const FSRef *) &extAppFSRef, kLSRolesAll,
|
||||
kLSItemDisplayName, (CFTypeRef *) &CFAppName);
|
||||
kLSItemDisplayName, (CFTypeRef *) &cfAppName);
|
||||
}
|
||||
if (CFAppName) {
|
||||
if (cfAppName) {
|
||||
nsAutoTArray<UniChar, 255> buffer;
|
||||
CFIndex appNameLength = ::CFStringGetLength(CFAppName);
|
||||
CFIndex appNameLength = ::CFStringGetLength(cfAppName);
|
||||
buffer.SetLength(appNameLength);
|
||||
::CFStringGetCharacters(CFAppName, CFRangeMake(0, appNameLength),
|
||||
::CFStringGetCharacters(cfAppName, CFRangeMake(0, appNameLength),
|
||||
buffer.Elements());
|
||||
nsAutoString appName;
|
||||
appName.Assign(buffer.Elements(), appNameLength);
|
||||
mimeInfoMac->SetDefaultDescription(appName);
|
||||
::CFRelease(CFAppName);
|
||||
::CFRelease(cfAppName);
|
||||
}
|
||||
|
||||
mimeInfoMac->SetDefaultApplication(app);
|
||||
@ -424,21 +537,22 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
|
||||
mimeInfoMac->AppendExtension(preferredExt);
|
||||
}
|
||||
|
||||
CFStringRef CFType = ::CFStringCreateWithCString(NULL, mimeType.get(), kCFStringEncodingUTF8);
|
||||
CFStringRef CFTypeDesc = NULL;
|
||||
if (::LSCopyKindStringForMIMEType(CFType, &CFTypeDesc) == noErr) {
|
||||
CFStringRef cfType = ::CFStringCreateWithCString(NULL, mimeType.get(), kCFStringEncodingUTF8);
|
||||
CFStringRef cfTypeDesc = NULL;
|
||||
if (::LSCopyKindStringForMIMEType(cfType, &cfTypeDesc) == noErr) {
|
||||
nsAutoTArray<UniChar, 255> buffer;
|
||||
CFIndex typeDescLength = ::CFStringGetLength(CFTypeDesc);
|
||||
CFIndex typeDescLength = ::CFStringGetLength(cfTypeDesc);
|
||||
buffer.SetLength(typeDescLength);
|
||||
::CFStringGetCharacters(CFTypeDesc, CFRangeMake(0, typeDescLength),
|
||||
::CFStringGetCharacters(cfTypeDesc, CFRangeMake(0, typeDescLength),
|
||||
buffer.Elements());
|
||||
nsAutoString typeDesc;
|
||||
typeDesc.Assign(buffer.Elements(), typeDescLength);
|
||||
mimeInfoMac->SetDescription(typeDesc);
|
||||
}
|
||||
if (CFTypeDesc)
|
||||
::CFRelease(CFTypeDesc);
|
||||
::CFRelease(CFType);
|
||||
if (cfTypeDesc) {
|
||||
::CFRelease(cfTypeDesc);
|
||||
}
|
||||
::CFRelease(cfType);
|
||||
}
|
||||
|
||||
PR_LOG(mLog, PR_LOG_DEBUG, ("OS gave us: type '%s' found '%i'\n", mimeType.get(), *aFound));
|
||||
|
@ -119,6 +119,10 @@ namespace mozilla {
|
||||
namespace gl {
|
||||
class TextureImage;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
class LayerManagerOGL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NP_NO_CARBON
|
||||
@ -295,6 +299,9 @@ typedef NSInteger NSEventGestureAxis;
|
||||
#ifdef __LP64__
|
||||
BOOL *mSwipeAnimationCancelled;
|
||||
#endif
|
||||
|
||||
// Whether this uses off-main-thread compositing.
|
||||
BOOL mUsingOMTCompositor;
|
||||
}
|
||||
|
||||
// class initialization
|
||||
@ -327,6 +334,8 @@ typedef NSInteger NSEventGestureAxis;
|
||||
// If so, we shouldn't focus or unfocus a plugin.
|
||||
- (BOOL)isInFailingLeftClickThrough;
|
||||
|
||||
- (void)setGLContext:(NSOpenGLContext *)aGLContext;
|
||||
|
||||
// Simple gestures support
|
||||
//
|
||||
// XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
|
||||
@ -348,6 +357,8 @@ typedef NSInteger NSEventGestureAxis;
|
||||
- (void)maybeTrackScrollEventAsSwipe:(NSEvent *)anEvent
|
||||
scrollOverflow:(PRInt32)overflow;
|
||||
#endif
|
||||
|
||||
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
|
||||
@end
|
||||
|
||||
class ChildViewMouseTracker {
|
||||
@ -433,7 +444,7 @@ public:
|
||||
|
||||
NS_IMETHOD SetCursor(nsCursor aCursor);
|
||||
NS_IMETHOD SetCursor(imgIContainer* aCursor, PRUint32 aHotspotX, PRUint32 aHotspotY);
|
||||
|
||||
|
||||
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, bool aDoCapture, bool aConsumeRollupEvent);
|
||||
NS_IMETHOD SetTitle(const nsAString& title);
|
||||
|
||||
@ -486,6 +497,7 @@ public:
|
||||
already_AddRefed<nsAccessible> GetDocumentAccessible();
|
||||
#endif
|
||||
|
||||
virtual void CreateCompositor();
|
||||
virtual gfxASurface* GetThebesSurface();
|
||||
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect);
|
||||
|
||||
|
@ -87,6 +87,7 @@
|
||||
#include "Layers.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/layers/CompositorCocoaWidgetHelper.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
@ -1772,6 +1773,22 @@ NSView<mozView>* nsChildView::GetEditorView()
|
||||
|
||||
#pragma mark -
|
||||
|
||||
void
|
||||
nsChildView::CreateCompositor()
|
||||
{
|
||||
nsBaseWidget::CreateCompositor();
|
||||
if (mCompositorChild) {
|
||||
LayerManagerOGL *manager =
|
||||
static_cast<LayerManagerOGL*>(compositor::GetLayerManager(mCompositorParent));
|
||||
|
||||
NSOpenGLContext *glContext =
|
||||
(NSOpenGLContext *) manager->gl()->GetNativeData(GLContext::NativeGLContext);
|
||||
|
||||
[(ChildView *)mView setGLContext:glContext];
|
||||
[(ChildView *)mView setUsingOMTCompositor:true];
|
||||
}
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
nsChildView::GetThebesSurface()
|
||||
{
|
||||
@ -2096,6 +2113,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)setGLContext:(NSOpenGLContext *)aGLContext
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
mGLContext = aGLContext;
|
||||
[mGLContext retain];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
@ -2546,13 +2573,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mGeckoChild->GetLayerManager(nsnull)->GetBackendType() == LayerManager::LAYERS_OPENGL) {
|
||||
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mGeckoChild->GetLayerManager(nsnull));
|
||||
manager->SetClippingRegion(paintEvent.region);
|
||||
LayerManager *layerManager = mGeckoChild->GetLayerManager(nsnull);
|
||||
if (layerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
|
||||
NSOpenGLContext *glContext;
|
||||
|
||||
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(layerManager);
|
||||
manager->SetClippingRegion(paintEvent.region);
|
||||
glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
|
||||
|
||||
if (!mGLContext) {
|
||||
mGLContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
|
||||
[mGLContext retain];
|
||||
[self setGLContext:glContext];
|
||||
}
|
||||
|
||||
mGeckoChild->DispatchWindowEvent(paintEvent);
|
||||
|
||||
// Force OpenGL to refresh the very first time we draw. This works around a
|
||||
@ -2592,6 +2624,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
painted = mGeckoChild->DispatchWindowEvent(paintEvent);
|
||||
}
|
||||
|
||||
// Force OpenGL to refresh the very first time we draw. This works around a
|
||||
// Mac OS X bug that stops windows updating on OS X when we use OpenGL.
|
||||
if (painted && !mDidForceRefreshOpenGL &&
|
||||
layerManager->AsShadowManager() && mUsingOMTCompositor) {
|
||||
if (!mDidForceRefreshOpenGL) {
|
||||
[self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
|
||||
mDidForceRefreshOpenGL = YES;
|
||||
}
|
||||
}
|
||||
|
||||
if (!painted && [self isOpaque]) {
|
||||
// Gecko refused to draw, but we've claimed to be opaque, so we have to
|
||||
// draw something--fill with white.
|
||||
@ -3129,6 +3171,12 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
}
|
||||
#endif // #ifdef __LP64__
|
||||
|
||||
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC
|
||||
{
|
||||
mUsingOMTCompositor = aUseOMTC;
|
||||
}
|
||||
|
||||
|
||||
// Returning NO from this method only disallows ordering on mousedown - in order
|
||||
// to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering]
|
||||
// when handling the mousedown event.
|
||||
|
@ -38,6 +38,8 @@
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "mozilla/layers/CompositorChild.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "nsBaseWidget.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -55,6 +57,7 @@
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "npapi.h"
|
||||
#include "base/thread.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nsIObserver.h"
|
||||
@ -70,6 +73,8 @@ static PRInt32 gNumWidgets;
|
||||
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla;
|
||||
using base::Thread;
|
||||
using mozilla::ipc::AsyncChannel;
|
||||
|
||||
nsIContent* nsBaseWidget::mLastRollup = nsnull;
|
||||
|
||||
@ -104,6 +109,7 @@ nsBaseWidget::nsBaseWidget()
|
||||
, mEventCallback(nsnull)
|
||||
, mViewCallback(nsnull)
|
||||
, mContext(nsnull)
|
||||
, mCompositorThread(nsnull)
|
||||
, mCursor(eCursor_standard)
|
||||
, mWindowType(eWindowType_child)
|
||||
, mBorderStyle(eBorderStyle_none)
|
||||
@ -142,6 +148,12 @@ nsBaseWidget::~nsBaseWidget()
|
||||
|
||||
if (mLayerManager) {
|
||||
mLayerManager->Destroy();
|
||||
mLayerManager = nsnull;
|
||||
}
|
||||
|
||||
if (mCompositorChild) {
|
||||
mCompositorChild->Destroy();
|
||||
delete mCompositorThread;
|
||||
}
|
||||
|
||||
#ifdef NOISY_WIDGET_LEAKS
|
||||
@ -814,6 +826,38 @@ nsBaseWidget::GetShouldAccelerate()
|
||||
return mUseAcceleratedRendering;
|
||||
}
|
||||
|
||||
void nsBaseWidget::CreateCompositor()
|
||||
{
|
||||
mCompositorParent = new CompositorParent(this);
|
||||
mCompositorThread = new Thread("CompositorThread");
|
||||
if (mCompositorThread->Start()) {
|
||||
LayerManager* lm = CreateBasicLayerManager();
|
||||
MessageLoop *childMessageLoop = mCompositorThread->message_loop();
|
||||
mCompositorChild = new CompositorChild(lm);
|
||||
AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
|
||||
AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
|
||||
mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
|
||||
PLayersChild* shadowManager =
|
||||
mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL);
|
||||
|
||||
if (shadowManager) {
|
||||
ShadowLayerForwarder* lf = lm->AsShadowForwarder();
|
||||
if (!lf) {
|
||||
delete lm;
|
||||
mCompositorChild = nsnull;
|
||||
}
|
||||
lf->SetShadowManager(shadowManager);
|
||||
lf->SetParentBackendType(LayerManager::LAYERS_OPENGL);
|
||||
|
||||
mLayerManager = lm;
|
||||
} else {
|
||||
NS_WARNING("fail to construct LayersChild");
|
||||
delete lm;
|
||||
mCompositorChild = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
|
||||
LayersBackend aBackendHint,
|
||||
LayerManagerPersistence aPersistence,
|
||||
@ -824,16 +868,29 @@ LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
|
||||
mUseAcceleratedRendering = GetShouldAccelerate();
|
||||
|
||||
if (mUseAcceleratedRendering) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
|
||||
/**
|
||||
* XXX - On several OSes initialization is expected to fail for now.
|
||||
* If we'd get a none-basic layer manager they'd crash. This is ok though
|
||||
* since on those platforms it will fail. Anyone implementing new
|
||||
* platforms on LayerManagerOGL should ensure their widget is able to
|
||||
* deal with it though!
|
||||
*/
|
||||
if (layerManager->Initialize()) {
|
||||
mLayerManager = layerManager;
|
||||
|
||||
// Try to use an async compositor first, if possible
|
||||
bool useCompositor =
|
||||
Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
|
||||
if (useCompositor) {
|
||||
// e10s uses the parameter to pass in the shadow manager from the TabChild
|
||||
// so we don't expect to see it there since this doesn't support e10s.
|
||||
NS_ASSERTION(aShadowManager == nsnull, "Async Compositor not supported with e10s");
|
||||
CreateCompositor();
|
||||
}
|
||||
|
||||
if (!mLayerManager) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
|
||||
/**
|
||||
* XXX - On several OSes initialization is expected to fail for now.
|
||||
* If we'd get a non-basic layer manager they'd crash. This is ok though
|
||||
* since on those platforms it will fail. Anyone implementing new
|
||||
* platforms on LayerManagerOGL should ensure their widget is able to
|
||||
* deal with it though!
|
||||
*/
|
||||
if (layerManager->Initialize()) {
|
||||
mLayerManager = layerManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mLayerManager) {
|
||||
|
@ -51,6 +51,17 @@ class nsIContent;
|
||||
class nsAutoRollup;
|
||||
class gfxContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class CompositorChild;
|
||||
class CompositorParent;
|
||||
}
|
||||
}
|
||||
|
||||
namespace base {
|
||||
class Thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common widget implementation used as base class for native
|
||||
* or crossplatform implementations of Widgets.
|
||||
@ -66,6 +77,9 @@ class nsBaseWidget : public nsIWidget
|
||||
|
||||
protected:
|
||||
typedef mozilla::layers::BasicLayerManager BasicLayerManager;
|
||||
typedef mozilla::layers::CompositorChild CompositorChild;
|
||||
typedef mozilla::layers::CompositorParent CompositorParent;
|
||||
typedef base::Thread Thread;
|
||||
|
||||
public:
|
||||
nsBaseWidget();
|
||||
@ -117,6 +131,7 @@ public:
|
||||
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
|
||||
bool* aAllowRetaining = nsnull);
|
||||
|
||||
virtual void CreateCompositor();
|
||||
virtual void DrawOver(LayerManager* aManager, nsIntRect aRect) {}
|
||||
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
|
||||
virtual gfxASurface* GetThebesSurface();
|
||||
@ -268,6 +283,9 @@ protected:
|
||||
nsDeviceContext* mContext;
|
||||
nsRefPtr<LayerManager> mLayerManager;
|
||||
nsRefPtr<LayerManager> mBasicLayerManager;
|
||||
nsRefPtr<CompositorChild> mCompositorChild;
|
||||
nsRefPtr<CompositorParent> mCompositorParent;
|
||||
Thread* mCompositorThread;
|
||||
nscolor mBackground;
|
||||
nscolor mForeground;
|
||||
nsCursor mCursor;
|
||||
|
@ -350,6 +350,22 @@ void* nsDeque::ObjectAt(PRInt32 aIndex) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void* nsDeque::RemoveObjectAt(PRInt32 aIndex) {
|
||||
if ((aIndex<0) || (aIndex>=mSize)) {
|
||||
return 0;
|
||||
}
|
||||
void* result=mData[modulus(mOrigin + aIndex, mCapacity)];
|
||||
|
||||
// "Shuffle down" all elements in the array by 1, overwritting the element
|
||||
// being removed.
|
||||
for (PRInt32 i=aIndex; i<mSize; i++) {
|
||||
mData[modulus(mOrigin + i, mCapacity)] = mData[modulus(mOrigin + i + 1, mCapacity)];
|
||||
}
|
||||
mSize--;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an iterator pointing to
|
||||
* the beginning of the queue. Note that this
|
||||
|
@ -152,6 +152,14 @@ class NS_COM_GLUE nsDeque {
|
||||
*/
|
||||
void* ObjectAt(int aIndex) const;
|
||||
|
||||
/**
|
||||
* Removes and returns the i'th member from the deque.
|
||||
*
|
||||
* @param index of desired item
|
||||
* @return the element which was removed
|
||||
*/
|
||||
void* RemoveObjectAt(int aIndex);
|
||||
|
||||
/**
|
||||
* Remove all items from container without destroying them.
|
||||
*
|
||||
|
@ -223,6 +223,39 @@ private:
|
||||
nsCOMPtr<nsISupports> mSupports;
|
||||
};
|
||||
|
||||
/**
|
||||
* hashkey wrapper using refcounted * KeyType
|
||||
*
|
||||
* @see nsTHashtable::EntryType for specification
|
||||
*/
|
||||
template<class T>
|
||||
class nsRefPtrHashKey : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef T* KeyType;
|
||||
typedef const T* KeyTypePointer;
|
||||
|
||||
nsRefPtrHashKey(const T* key) :
|
||||
mKey(const_cast<T*>(key)) { }
|
||||
nsRefPtrHashKey(const nsRefPtrHashKey& toCopy) :
|
||||
mKey(toCopy.mKey) { }
|
||||
~nsRefPtrHashKey() { }
|
||||
|
||||
KeyType GetKey() const { return mKey; }
|
||||
|
||||
bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
||||
{
|
||||
return NS_PTR_TO_INT32(aKey) >>2;
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
private:
|
||||
nsRefPtr<T> mKey;
|
||||
};
|
||||
|
||||
/**
|
||||
* hashkey wrapper using T* KeyType
|
||||
*
|
||||
|
@ -89,6 +89,7 @@ CPP_UNIT_TESTS = \
|
||||
TestCOMArray.cpp \
|
||||
TestCOMPtr.cpp \
|
||||
TestCOMPtrEq.cpp \
|
||||
TestDeque.cpp \
|
||||
TestFile.cpp \
|
||||
TestHashtables.cpp \
|
||||
TestID.cpp \
|
||||
@ -109,7 +110,6 @@ endif
|
||||
#CPP_UNIT_TESTS += \
|
||||
# TestArray.cpp \
|
||||
# TestCRT.cpp \
|
||||
# TestDeque.cpp \
|
||||
# TestEncoding.cpp \
|
||||
# TestExpirationTracker.cpp \
|
||||
# TestPipes.cpp \
|
||||
|
@ -35,6 +35,7 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "TestHarness.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsCRT.h"
|
||||
#include <stdio.h>
|
||||
@ -44,13 +45,12 @@
|
||||
**************************************************************/
|
||||
class _TestDeque {
|
||||
public:
|
||||
_TestDeque() {
|
||||
SelfTest();
|
||||
}
|
||||
int SelfTest();
|
||||
nsresult OriginalTest();
|
||||
nsresult OriginalFlaw();
|
||||
nsresult AssignFlaw();
|
||||
int Test();
|
||||
private:
|
||||
int OriginalTest();
|
||||
int OriginalFlaw();
|
||||
int AssignFlaw();
|
||||
int TestRemove();
|
||||
};
|
||||
static _TestDeque sTestDeque;
|
||||
|
||||
@ -60,96 +60,214 @@ class _Dealloc: public nsDequeFunctor {
|
||||
}
|
||||
};
|
||||
|
||||
#define TEST(aCondition, aMsg) \
|
||||
if (!(aCondition)) { fail("TestDeque: "#aMsg); return 1; }
|
||||
|
||||
|
||||
/**
|
||||
* conduct automated self test for this class
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int _TestDeque::SelfTest() {
|
||||
int _TestDeque::Test() {
|
||||
/* the old deque should have failed a bunch of these tests */
|
||||
int results=0;
|
||||
results+=OriginalTest();
|
||||
results+=OriginalFlaw();
|
||||
results+=AssignFlaw();
|
||||
results+=TestRemove();
|
||||
return results;
|
||||
}
|
||||
|
||||
nsresult _TestDeque::OriginalTest() {
|
||||
int ints[200];
|
||||
int count=sizeof(ints)/sizeof(int);
|
||||
int _TestDeque::OriginalTest() {
|
||||
const int size = 200;
|
||||
int ints[size];
|
||||
int i=0;
|
||||
int* temp;
|
||||
int temp;
|
||||
nsDeque theDeque(new _Dealloc); //construct a simple one...
|
||||
|
||||
for (i=0;i<count;i++) { //initialize'em
|
||||
ints[i]=10*(1+i);
|
||||
// ints = [0...199]
|
||||
for (i=0;i<size;i++) { //initialize'em
|
||||
ints[i]=i;
|
||||
}
|
||||
// queue = [0...69]
|
||||
for (i=0;i<70;i++) {
|
||||
theDeque.Push(&ints[i]);
|
||||
temp=*(int*)theDeque.Peek();
|
||||
TEST(temp == i, "Verify end after push #1");
|
||||
TEST(theDeque.GetSize() == i + 1, "Verify size after push #1");
|
||||
}
|
||||
for (i=0;i<56;i++) {
|
||||
temp=(int*)theDeque.Pop();
|
||||
TEST(theDeque.GetSize() == 70, "Verify overall size after pushes #1");
|
||||
// queue = [0...14]
|
||||
for (i=1;i<=55;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 70-i, "Verify end after pop # 1");
|
||||
TEST(theDeque.GetSize() == 70 - i, "Verify size after pop # 1");
|
||||
}
|
||||
TEST(theDeque.GetSize() == 15, "Verify overall size after pops");
|
||||
|
||||
// queue = [0...14,0...54]
|
||||
for (i=0;i<55;i++) {
|
||||
theDeque.Push(&ints[i]);
|
||||
temp=*(int*)theDeque.Peek();
|
||||
TEST(temp == i, "Verify end after push #2");
|
||||
TEST(theDeque.GetSize() == i + 15 + 1, "Verify size after push # 2");
|
||||
}
|
||||
for (i=0;i<35;i++) {
|
||||
temp=(int*)theDeque.Pop();
|
||||
TEST(theDeque.GetSize() == 70, "Verify size after end of all pushes #2");
|
||||
|
||||
// queue = [0...14,0...19]
|
||||
for (i=1;i<=35;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 55-i, "Verify end after pop # 2");
|
||||
TEST(theDeque.GetSize() == 70 - i, "Verify size after pop #2");
|
||||
}
|
||||
TEST(theDeque.GetSize() == 35, "Verify overall size after end of all pops #2");
|
||||
|
||||
// queue = [0...14,0...19,0...34]
|
||||
for (i=0;i<35;i++) {
|
||||
theDeque.Push(&ints[i]);
|
||||
temp = *(int*)theDeque.Peek();
|
||||
TEST(temp == i, "Verify end after push # 3");
|
||||
TEST(theDeque.GetSize() == 35 + 1 + i, "Verify size after push #3");
|
||||
}
|
||||
for (i=0;i<38;i++) {
|
||||
temp=(int*)theDeque.Pop();
|
||||
|
||||
// queue = [0...14,0...19]
|
||||
for (i=0;i<35;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 34 - i, "Verify end after pop # 3");
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
// queue = [0...14]
|
||||
for (i=0;i<20;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 19 - i, "Verify end after pop # 4");
|
||||
}
|
||||
|
||||
// queue = []
|
||||
for (i=0;i<15;i++) {
|
||||
temp=*(int*)theDeque.Pop();
|
||||
TEST(temp == 14 - i, "Verify end after pop # 5");
|
||||
}
|
||||
|
||||
TEST(theDeque.GetSize() == 0, "Deque should finish empty.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult _TestDeque::OriginalFlaw() {
|
||||
int _TestDeque::OriginalFlaw() {
|
||||
int ints[200];
|
||||
int i=0;
|
||||
int* temp;
|
||||
nsDeque secondDeque(new _Dealloc);
|
||||
int temp;
|
||||
nsDeque d(new _Dealloc);
|
||||
/**
|
||||
* Test 1. Origin near end, semi full, call Peek().
|
||||
* you start, mCapacity is 8
|
||||
*/
|
||||
printf("fill array\n");
|
||||
for (i=32; i; --i)
|
||||
ints[i]=i*3+10;
|
||||
printf("push 6 times\n");
|
||||
for (i=0; i<6; i++)
|
||||
secondDeque.Push(&ints[i]);
|
||||
printf("popfront 4 times:\n");
|
||||
for (i=4; i; --i) {
|
||||
temp=(int*)secondDeque.PopFront();
|
||||
printf("%d\t",*temp);
|
||||
for (i=0; i<30; i++)
|
||||
ints[i]=i;
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
d.Push(&ints[i]);
|
||||
temp = *(int*)d.Peek();
|
||||
TEST(temp == i, "OriginalFlaw push #1");
|
||||
}
|
||||
printf("push 4 times\n");
|
||||
for (int j=4; j; --j)
|
||||
secondDeque.Push(&ints[++i]);
|
||||
printf("origin should now be about 4\n");
|
||||
printf("and size should be 6\n");
|
||||
printf("origin+size>capacity\n");
|
||||
TEST(d.GetSize() == 6, "OriginalFlaw size check #1");
|
||||
|
||||
/*<akk> Oh, I see ... it's a circular buffer */
|
||||
printf("but the old code wasn't behaving accordingly.\n");
|
||||
for (i=0; i<4; i++) {
|
||||
temp=*(int*)d.PopFront();
|
||||
TEST(temp == i, "PopFront test");
|
||||
}
|
||||
// d = [4,5]
|
||||
TEST(d.GetSize() == 2, "OriginalFlaw size check #2");
|
||||
|
||||
/*right*/
|
||||
printf("we shouldn't crash or anything interesting, ");
|
||||
for (i=0; i<4; i++) {
|
||||
d.Push(&ints[6 + i]);
|
||||
}
|
||||
// d = [4...9]
|
||||
|
||||
temp=(int*)secondDeque.Peek();
|
||||
printf("peek: %d\n",*temp);
|
||||
return NS_OK;
|
||||
for (i=4; i<=9; i++) {
|
||||
temp=*(int*)d.PopFront();
|
||||
TEST(temp == i, "OriginalFlaw empty check");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult _TestDeque::AssignFlaw() {
|
||||
int _TestDeque::AssignFlaw() {
|
||||
nsDeque src(new _Dealloc),dest(new _Dealloc);
|
||||
return NS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool VerifyContents(const nsDeque& aDeque, const int* aContents, int aLength) {
|
||||
for (int i=0; i<aLength; ++i) {
|
||||
if (*(int*)aDeque.ObjectAt(i) != aContents[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int _TestDeque::TestRemove() {
|
||||
nsDeque d;
|
||||
const int count = 10;
|
||||
int ints[count];
|
||||
for (int i=0; i<count; i++) {
|
||||
ints[i] = i;
|
||||
}
|
||||
|
||||
for (int i=0; i<6; i++) {
|
||||
d.Push(&ints[i]);
|
||||
}
|
||||
// d = [0...5]
|
||||
d.PopFront();
|
||||
d.PopFront();
|
||||
|
||||
// d = [2,5]
|
||||
for (int i=2; i<=5; i++) {
|
||||
int t = *(int*)d.ObjectAt(i-2);
|
||||
TEST(t == i, "Verify ObjectAt()");
|
||||
}
|
||||
|
||||
d.RemoveObjectAt(1);
|
||||
// d == [2,4,5]
|
||||
static const int t1[] = {2,4,5};
|
||||
TEST(VerifyContents(d, t1, 3), "verify contents t1");
|
||||
|
||||
d.PushFront(&ints[1]);
|
||||
d.PushFront(&ints[0]);
|
||||
d.PushFront(&ints[7]);
|
||||
d.PushFront(&ints[6]);
|
||||
// d == [6,7,0,1,2,4,5] // (0==mOrigin)
|
||||
static const int t2[] = {6,7,0,1,2,4,5};
|
||||
TEST(VerifyContents(d, t2, 7), "verify contents t2");
|
||||
|
||||
d.RemoveObjectAt(1);
|
||||
// d == [6,0,1,2,4,5] // (1==mOrigin)
|
||||
static const int t3[] = {6,0,1,2,4,5};
|
||||
TEST(VerifyContents(d, t3, 6), "verify contents t3");
|
||||
|
||||
d.RemoveObjectAt(5);
|
||||
// d == [6,0,1,2,4] // (1==mOrigin)
|
||||
static const int t4[] = {6,0,1,2,4};
|
||||
TEST(VerifyContents(d, t4, 5), "verify contents t4");
|
||||
|
||||
d.RemoveObjectAt(0);
|
||||
// d == [0,1,2,4] // (2==mOrigin)
|
||||
static const int t5[] = {0,1,2,4};
|
||||
TEST(VerifyContents(d, t5, 4), "verify contents t5");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
ScopedXPCOM xpcom("TestTimers");
|
||||
NS_ENSURE_FALSE(xpcom.failed(), 1);
|
||||
|
||||
_TestDeque test;
|
||||
int result = test.Test();
|
||||
TEST(result == 0, "All tests pass");
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user