зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to s-c.
This commit is contained in:
Коммит
80a3f4f3ee
|
@ -141,11 +141,6 @@ struct MaiAtkObjectClass
|
|||
|
||||
static guint mai_atk_object_signals [LAST_SIGNAL] = { 0, };
|
||||
|
||||
#ifdef MAI_LOGGING
|
||||
int32_t sMaiAtkObjCreated = 0;
|
||||
int32_t sMaiAtkObjDeleted = 0;
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
/* callbacks for MaiAtkObject */
|
||||
static void classInitCB(AtkObjectClass *aClass);
|
||||
|
@ -232,33 +227,15 @@ mai_atk_object_get_type(void)
|
|||
return type;
|
||||
}
|
||||
|
||||
#ifdef MAI_LOGGING
|
||||
int32_t AccessibleWrap::mAccWrapCreated = 0;
|
||||
int32_t AccessibleWrap::mAccWrapDeleted = 0;
|
||||
#endif
|
||||
|
||||
AccessibleWrap::
|
||||
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
Accessible(aContent, aDoc), mAtkObject(nullptr)
|
||||
{
|
||||
#ifdef MAI_LOGGING
|
||||
++mAccWrapCreated;
|
||||
#endif
|
||||
MAI_LOG_DEBUG(("==AccessibleWrap creating: this=%p,total=%d left=%d\n",
|
||||
(void*)this, mAccWrapCreated,
|
||||
(mAccWrapCreated-mAccWrapDeleted)));
|
||||
}
|
||||
|
||||
AccessibleWrap::~AccessibleWrap()
|
||||
{
|
||||
NS_ASSERTION(!mAtkObject, "ShutdownAtkObject() is not called");
|
||||
|
||||
#ifdef MAI_LOGGING
|
||||
++mAccWrapDeleted;
|
||||
#endif
|
||||
MAI_LOG_DEBUG(("==AccessibleWrap deleting: this=%p,total=%d left=%d\n",
|
||||
(void*)this, mAccWrapDeleted,
|
||||
(mAccWrapCreated-mAccWrapDeleted)));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -482,8 +459,6 @@ GetUniqueMaiAtkTypeName(uint16_t interfacesBits)
|
|||
interfacesBits);
|
||||
name[MAI_ATK_TYPE_NAME_LEN] = '\0';
|
||||
|
||||
MAI_LOG_DEBUG(("MaiWidget::LastedTypeName=%s\n", name));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -603,13 +578,6 @@ initializeCB(AtkObject *aAtkObj, gpointer aData)
|
|||
/* initialize object */
|
||||
MAI_ATK_OBJECT(aAtkObj)->accWrap =
|
||||
static_cast<AccessibleWrap*>(aData);
|
||||
|
||||
#ifdef MAI_LOGGING
|
||||
++sMaiAtkObjCreated;
|
||||
#endif
|
||||
MAI_LOG_DEBUG(("MaiAtkObj Create obj=%p for AccWrap=%p, all=%d, left=%d\n",
|
||||
(void*)aAtkObj, (void*)aData, sMaiAtkObjCreated,
|
||||
(sMaiAtkObjCreated-sMaiAtkObjDeleted)));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -619,13 +587,6 @@ finalizeCB(GObject *aObj)
|
|||
return;
|
||||
NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap == nullptr, "AccWrap NOT null");
|
||||
|
||||
#ifdef MAI_LOGGING
|
||||
++sMaiAtkObjDeleted;
|
||||
#endif
|
||||
MAI_LOG_DEBUG(("MaiAtkObj Delete obj=%p, all=%d, left=%d\n",
|
||||
(void*)aObj, sMaiAtkObjCreated,
|
||||
(sMaiAtkObjCreated-sMaiAtkObjDeleted)));
|
||||
|
||||
// call parent finalize function
|
||||
// finalize of GObjectClass will unref the accessible parent if has
|
||||
if (G_OBJECT_CLASS (parent_class)->finalize)
|
||||
|
@ -992,7 +953,6 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
|
||||
case nsIAccessibleEvent::EVENT_FOCUS:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
|
||||
a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible();
|
||||
if (rootAccWrap && rootAccWrap->mActivated) {
|
||||
atk_focus_tracker_notify(atkObj);
|
||||
|
@ -1015,7 +975,6 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
}
|
||||
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_VALUE_CHANGE\n"));
|
||||
nsCOMPtr<nsIAccessibleValue> value(do_QueryObject(accessible));
|
||||
if (value) { // Make sure this is a numeric value
|
||||
// Don't fire for MSAA string value changes (e.g. text editing)
|
||||
|
@ -1029,7 +988,6 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
case nsIAccessibleEvent::EVENT_SELECTION_REMOVE:
|
||||
{
|
||||
// XXX: dupe events may be fired
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_SELECTION_CHANGED\n"));
|
||||
AccSelChangeEvent* selChangeEvent = downcast_accEvent(aEvent);
|
||||
g_signal_emit_by_name(AccessibleWrap::GetAtkObject(selChangeEvent->Widget()),
|
||||
"selection_changed");
|
||||
|
@ -1038,128 +996,86 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
|
||||
case nsIAccessibleEvent::EVENT_SELECTION_WITHIN:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_SELECTION_CHANGED\n"));
|
||||
g_signal_emit_by_name(atkObj, "selection_changed");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_SELECTION_CHANGED\n"));
|
||||
g_signal_emit_by_name(atkObj, "text_selection_changed");
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_CARET_MOVED\n"));
|
||||
|
||||
AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(aEvent);
|
||||
NS_ASSERTION(caretMoveEvent, "Event needs event data");
|
||||
if (!caretMoveEvent)
|
||||
break;
|
||||
|
||||
int32_t caretOffset = caretMoveEvent->GetCaretOffset();
|
||||
|
||||
MAI_LOG_DEBUG(("\n\nCaret postion: %d", caretOffset));
|
||||
g_signal_emit_by_name(atkObj,
|
||||
"text_caret_moved",
|
||||
// Curent caret position
|
||||
caretOffset);
|
||||
g_signal_emit_by_name(atkObj, "text_caret_moved", caretOffset);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_ATTRIBUTE_CHANGED\n"));
|
||||
|
||||
g_signal_emit_by_name(atkObj,
|
||||
"text-attributes-changed");
|
||||
g_signal_emit_by_name(atkObj, "text-attributes-changed");
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_MODEL_CHANGED\n"));
|
||||
g_signal_emit_by_name(atkObj, "model_changed");
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_ROW_INSERT:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_INSERT\n"));
|
||||
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
|
||||
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
|
||||
|
||||
int32_t rowIndex = tableEvent->GetIndex();
|
||||
int32_t numRows = tableEvent->GetCount();
|
||||
|
||||
g_signal_emit_by_name(atkObj,
|
||||
"row_inserted",
|
||||
// After which the rows are inserted
|
||||
rowIndex,
|
||||
// The number of the inserted
|
||||
numRows);
|
||||
g_signal_emit_by_name(atkObj, "row_inserted", rowIndex, numRows);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_ROW_DELETE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_DELETE\n"));
|
||||
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
|
||||
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
|
||||
|
||||
int32_t rowIndex = tableEvent->GetIndex();
|
||||
int32_t numRows = tableEvent->GetCount();
|
||||
|
||||
g_signal_emit_by_name(atkObj,
|
||||
"row_deleted",
|
||||
// After which the rows are deleted
|
||||
rowIndex,
|
||||
// The number of the deleted
|
||||
numRows);
|
||||
g_signal_emit_by_name(atkObj, "row_deleted", rowIndex, numRows);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_ROW_REORDER:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_REORDER\n"));
|
||||
g_signal_emit_by_name(atkObj, "row_reordered");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_INSERT:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_INSERT\n"));
|
||||
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
|
||||
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
|
||||
|
||||
int32_t colIndex = tableEvent->GetIndex();
|
||||
int32_t numCols = tableEvent->GetCount();
|
||||
|
||||
g_signal_emit_by_name(atkObj,
|
||||
"column_inserted",
|
||||
// After which the columns are inserted
|
||||
colIndex,
|
||||
// The number of the inserted
|
||||
numCols);
|
||||
g_signal_emit_by_name(atkObj, "column_inserted", colIndex, numCols);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_DELETE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_DELETE\n"));
|
||||
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
|
||||
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
|
||||
|
||||
int32_t colIndex = tableEvent->GetIndex();
|
||||
int32_t numCols = tableEvent->GetCount();
|
||||
|
||||
g_signal_emit_by_name(atkObj,
|
||||
"column_deleted",
|
||||
// After which the columns are deleted
|
||||
colIndex,
|
||||
// The number of the deleted
|
||||
numCols);
|
||||
g_signal_emit_by_name(atkObj, "column_deleted", colIndex, numCols);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_REORDER:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_REORDER\n"));
|
||||
g_signal_emit_by_name(atkObj, "column_reordered");
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_SECTION_CHANGED:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_SECTION_CHANGED\n"));
|
||||
g_signal_emit_by_name(atkObj, "visible_data_changed");
|
||||
break;
|
||||
|
||||
|
@ -1176,16 +1092,11 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
* Need more verification by AT test.
|
||||
*/
|
||||
case nsIAccessibleEvent::EVENT_MENU_START:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENU_START\n"));
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_MENU_END:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENU_END\n"));
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_ACTIVATED\n"));
|
||||
accessible->AsRoot()->mActivated = true;
|
||||
guint id = g_signal_lookup ("activate", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
|
@ -1196,7 +1107,6 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_DEACTIVATED\n"));
|
||||
accessible->AsRoot()->mActivated = false;
|
||||
guint id = g_signal_lookup ("deactivate", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
|
@ -1204,52 +1114,41 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
|||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_MAXIMIZE\n"));
|
||||
guint id = g_signal_lookup ("maximize", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_MINIMIZE\n"));
|
||||
guint id = g_signal_lookup ("minimize", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_WINDOW_RESTORE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_RESTORE\n"));
|
||||
guint id = g_signal_lookup ("restore", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit(atkObj, id, 0);
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_COMPLETE\n"));
|
||||
g_signal_emit_by_name (atkObj, "load_complete");
|
||||
} break;
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_RELOAD\n"));
|
||||
g_signal_emit_by_name (atkObj, "reload");
|
||||
} break;
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_STOPPED\n"));
|
||||
g_signal_emit_by_name (atkObj, "load_stopped");
|
||||
} break;
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUPOPUP_START\n"));
|
||||
atk_focus_tracker_notify(atkObj); // fire extra focus event
|
||||
atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, true);
|
||||
atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true);
|
||||
break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUPOPUP_END\n"));
|
||||
atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, false);
|
||||
atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, false);
|
||||
break;
|
||||
|
@ -1262,8 +1161,6 @@ nsresult
|
|||
AccessibleWrap::FireAtkStateChangeEvent(AccEvent* aEvent,
|
||||
AtkObject* aObject)
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_STATE_CHANGE\n"));
|
||||
|
||||
AccStateChangeEvent* event = downcast_accEvent(aEvent);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -1294,8 +1191,6 @@ nsresult
|
|||
AccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
|
||||
AtkObject* aObject)
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_REMOVED/INSERTED\n"));
|
||||
|
||||
AccTextChangeEvent* event = downcast_accEvent(aEvent);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -1335,12 +1230,6 @@ nsresult
|
|||
AccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
|
||||
AtkObject* aObject, bool aIsAdded)
|
||||
{
|
||||
if (aIsAdded) {
|
||||
MAI_LOG_DEBUG(("\n\nReceived: Show event\n"));
|
||||
} else {
|
||||
MAI_LOG_DEBUG(("\n\nReceived: Hide event\n"));
|
||||
}
|
||||
|
||||
int32_t indexInParent = getIndexInParentCB(aObject);
|
||||
AtkObject *parentObject = getParentCB(aObject);
|
||||
NS_ENSURE_STATE(parentObject);
|
||||
|
|
|
@ -9,11 +9,6 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "Accessible.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
#define MAI_LOGGING
|
||||
#endif /* #ifdef PR_LOGGING */
|
||||
|
||||
struct _AtkObject;
|
||||
typedef struct _AtkObject AtkObject;
|
||||
|
@ -60,12 +55,6 @@ public:
|
|||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
#ifdef MAI_LOGGING
|
||||
virtual void DumpAccessibleWrapInfo(int aDepth) {}
|
||||
static int32_t mAccWrapCreated;
|
||||
static int32_t mAccWrapDeleted;
|
||||
#endif
|
||||
|
||||
// return the atk object for this AccessibleWrap
|
||||
NS_IMETHOD GetNativeInterface(void **aOutAccessible);
|
||||
virtual nsresult HandleAccEvent(AccEvent* aEvent);
|
||||
|
|
|
@ -33,57 +33,6 @@ static const char sATKLibName[] = "libatk-1.0.so.0";
|
|||
static const char sATKHyperlinkImplGetTypeSymbol[] =
|
||||
"atk_hyperlink_impl_get_type";
|
||||
|
||||
/* gail function pointer */
|
||||
static guint (* gail_add_global_event_listener) (GSignalEmissionHook listener,
|
||||
const gchar *event_type);
|
||||
static void (* gail_remove_global_event_listener) (guint remove_listener);
|
||||
static void (* gail_remove_key_event_listener) (guint remove_listener);
|
||||
static AtkObject * (*gail_get_root) (void);
|
||||
|
||||
/* maiutil */
|
||||
|
||||
static guint mai_util_add_global_event_listener(GSignalEmissionHook listener,
|
||||
const gchar *event_type);
|
||||
static void mai_util_remove_global_event_listener(guint remove_listener);
|
||||
static guint mai_util_add_key_event_listener(AtkKeySnoopFunc listener,
|
||||
gpointer data);
|
||||
static void mai_util_remove_key_event_listener(guint remove_listener);
|
||||
static AtkObject *mai_util_get_root(void);
|
||||
static G_CONST_RETURN gchar *mai_util_get_toolkit_name(void);
|
||||
static G_CONST_RETURN gchar *mai_util_get_toolkit_version(void);
|
||||
|
||||
|
||||
/* Misc */
|
||||
|
||||
static void _listener_info_destroy(gpointer data);
|
||||
static guint add_listener (GSignalEmissionHook listener,
|
||||
const gchar *object_type,
|
||||
const gchar *signal,
|
||||
const gchar *hook_data,
|
||||
guint gail_listenerid = 0);
|
||||
static AtkKeyEventStruct *atk_key_event_from_gdk_event_key(GdkEventKey *key);
|
||||
static gboolean notify_hf(gpointer key, gpointer value, gpointer data);
|
||||
static void insert_hf(gpointer key, gpointer value, gpointer data);
|
||||
static gint mai_key_snooper(GtkWidget *the_widget, GdkEventKey *event,
|
||||
gpointer func_data);
|
||||
|
||||
static GHashTable* sListener_list = NULL;
|
||||
static gint sListener_idx = 1;
|
||||
|
||||
#define MAI_TYPE_UTIL (mai_util_get_type ())
|
||||
#define MAI_UTIL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
MAI_TYPE_UTIL, MaiUtil))
|
||||
#define MAI_UTIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
MAI_TYPE_UTIL, MaiUtilClass))
|
||||
#define MAI_IS_UTIL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
MAI_TYPE_UTIL))
|
||||
#define MAI_IS_UTIL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
MAI_TYPE_UTIL))
|
||||
#define MAI_UTIL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
MAI_TYPE_UTIL, MaiUtilClass))
|
||||
|
||||
static GHashTable* sKey_listener_list = NULL;
|
||||
static guint sKey_snooper_id = 0;
|
||||
static bool sToplevel_event_hook_added = false;
|
||||
static gulong sToplevel_show_hook = 0;
|
||||
static gulong sToplevel_hide_hook = 0;
|
||||
|
@ -93,24 +42,6 @@ typedef void (*GnomeAccessibilityInit) (void);
|
|||
typedef void (*GnomeAccessibilityShutdown) (void);
|
||||
G_END_DECLS
|
||||
|
||||
struct MaiUtil
|
||||
{
|
||||
AtkUtil parent;
|
||||
GList *listener_list;
|
||||
};
|
||||
|
||||
struct MaiKeyEventInfo
|
||||
{
|
||||
AtkKeyEventStruct *key_event;
|
||||
gpointer func_data;
|
||||
};
|
||||
|
||||
union AtkKeySnoopFuncPointer
|
||||
{
|
||||
AtkKeySnoopFunc func_ptr;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
struct GnomeAccessibilityModule
|
||||
{
|
||||
const char *libName;
|
||||
|
@ -121,32 +52,6 @@ struct GnomeAccessibilityModule
|
|||
GnomeAccessibilityShutdown shutdown;
|
||||
};
|
||||
|
||||
struct MaiUtilClass
|
||||
{
|
||||
AtkUtilClass parent_class;
|
||||
};
|
||||
|
||||
GType mai_util_get_type (void);
|
||||
static void mai_util_class_init(MaiUtilClass *klass);
|
||||
|
||||
/* supporting */
|
||||
PRLogModuleInfo *gMaiLog = NULL;
|
||||
|
||||
#define MAI_VERSION MOZILLA_VERSION
|
||||
#define MAI_NAME "Gecko"
|
||||
|
||||
struct MaiUtilListenerInfo
|
||||
{
|
||||
gint key;
|
||||
guint signal_id;
|
||||
gulong hook_id;
|
||||
// For window create/destory/minimize/maximize/restore/activate/deactivate
|
||||
// events, we'll chain gail_util's add/remove_global_event_listener.
|
||||
// So we store the listenerid returned by gail's add_global_event_listener
|
||||
// in this structure to call gail's remove_global_event_listener later.
|
||||
guint gail_listenerid;
|
||||
};
|
||||
|
||||
static GnomeAccessibilityModule sAtkBridge = {
|
||||
#ifdef AIX
|
||||
"libatk-bridge.a(libatk-bridge.so.0)", NULL,
|
||||
|
@ -163,352 +68,6 @@ static GnomeAccessibilityModule sGail = {
|
|||
"gnome_accessibility_module_shutdown", NULL
|
||||
};
|
||||
|
||||
GType
|
||||
mai_util_get_type(void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (!type) {
|
||||
static const GTypeInfo tinfo = {
|
||||
sizeof(MaiUtilClass),
|
||||
(GBaseInitFunc) NULL, /* base init */
|
||||
(GBaseFinalizeFunc) NULL, /* base finalize */
|
||||
(GClassInitFunc) mai_util_class_init, /* class init */
|
||||
(GClassFinalizeFunc) NULL, /* class finalize */
|
||||
NULL, /* class data */
|
||||
sizeof(MaiUtil), /* instance size */
|
||||
0, /* nb preallocs */
|
||||
(GInstanceInitFunc) NULL, /* instance init */
|
||||
NULL /* value table */
|
||||
};
|
||||
|
||||
type = g_type_register_static(ATK_TYPE_UTIL,
|
||||
"MaiUtil", &tinfo, GTypeFlags(0));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
window_added (AtkObject *atk_obj,
|
||||
guint index,
|
||||
AtkObject *child)
|
||||
{
|
||||
if (!IS_MAI_OBJECT(child))
|
||||
return;
|
||||
|
||||
static guint id = g_signal_lookup ("create", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit (child, id, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_removed (AtkObject *atk_obj,
|
||||
guint index,
|
||||
AtkObject *child)
|
||||
{
|
||||
if (!IS_MAI_OBJECT(child))
|
||||
return;
|
||||
|
||||
static guint id = g_signal_lookup ("destroy", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit (child, id, 0);
|
||||
}
|
||||
|
||||
/* intialize the the atk interface (function pointers) with MAI implementation.
|
||||
* When atk bridge get loaded, these interface can be used.
|
||||
*/
|
||||
static void
|
||||
mai_util_class_init(MaiUtilClass *klass)
|
||||
{
|
||||
AtkUtilClass *atk_class;
|
||||
gpointer data;
|
||||
|
||||
data = g_type_class_peek(ATK_TYPE_UTIL);
|
||||
atk_class = ATK_UTIL_CLASS(data);
|
||||
|
||||
// save gail function pointer
|
||||
gail_add_global_event_listener = atk_class->add_global_event_listener;
|
||||
gail_remove_global_event_listener = atk_class->remove_global_event_listener;
|
||||
gail_remove_key_event_listener = atk_class->remove_key_event_listener;
|
||||
gail_get_root = atk_class->get_root;
|
||||
|
||||
atk_class->add_global_event_listener =
|
||||
mai_util_add_global_event_listener;
|
||||
atk_class->remove_global_event_listener =
|
||||
mai_util_remove_global_event_listener;
|
||||
atk_class->add_key_event_listener = mai_util_add_key_event_listener;
|
||||
atk_class->remove_key_event_listener = mai_util_remove_key_event_listener;
|
||||
atk_class->get_root = mai_util_get_root;
|
||||
atk_class->get_toolkit_name = mai_util_get_toolkit_name;
|
||||
atk_class->get_toolkit_version = mai_util_get_toolkit_version;
|
||||
|
||||
sListener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
|
||||
_listener_info_destroy);
|
||||
// Keep track of added/removed windows.
|
||||
AtkObject *root = atk_get_root ();
|
||||
g_signal_connect (root, "children-changed::add", (GCallback) window_added, NULL);
|
||||
g_signal_connect (root, "children-changed::remove", (GCallback) window_removed, NULL);
|
||||
}
|
||||
|
||||
static guint
|
||||
mai_util_add_global_event_listener(GSignalEmissionHook listener,
|
||||
const gchar *event_type)
|
||||
{
|
||||
guint rc = 0;
|
||||
gchar **split_string;
|
||||
|
||||
split_string = g_strsplit (event_type, ":", 3);
|
||||
|
||||
if (split_string) {
|
||||
if (!strcmp ("window", split_string[0])) {
|
||||
guint gail_listenerid = 0;
|
||||
if (gail_add_global_event_listener) {
|
||||
// call gail's function to track gtk native window events
|
||||
gail_listenerid =
|
||||
gail_add_global_event_listener(listener, event_type);
|
||||
}
|
||||
|
||||
rc = add_listener (listener, "MaiAtkObject", split_string[1],
|
||||
event_type, gail_listenerid);
|
||||
}
|
||||
else {
|
||||
rc = add_listener (listener, split_string[1], split_string[2],
|
||||
event_type);
|
||||
}
|
||||
g_strfreev(split_string);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
mai_util_remove_global_event_listener(guint remove_listener)
|
||||
{
|
||||
if (remove_listener > 0) {
|
||||
MaiUtilListenerInfo *listener_info;
|
||||
gint tmp_idx = remove_listener;
|
||||
|
||||
listener_info = (MaiUtilListenerInfo *)
|
||||
g_hash_table_lookup(sListener_list, &tmp_idx);
|
||||
|
||||
if (listener_info != NULL) {
|
||||
if (gail_remove_global_event_listener &&
|
||||
listener_info->gail_listenerid) {
|
||||
gail_remove_global_event_listener(listener_info->gail_listenerid);
|
||||
}
|
||||
|
||||
/* Hook id of 0 and signal id of 0 are invalid */
|
||||
if (listener_info->hook_id != 0 && listener_info->signal_id != 0) {
|
||||
/* Remove the emission hook */
|
||||
g_signal_remove_emission_hook(listener_info->signal_id,
|
||||
listener_info->hook_id);
|
||||
|
||||
/* Remove the element from the hash */
|
||||
g_hash_table_remove(sListener_list, &tmp_idx);
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid listener hook_id %ld or signal_id %d\n",
|
||||
listener_info->hook_id, listener_info->signal_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// atk-bridge is initialized with gail (e.g. yelp)
|
||||
// try gail_remove_global_event_listener
|
||||
if (gail_remove_global_event_listener) {
|
||||
return gail_remove_global_event_listener(remove_listener);
|
||||
}
|
||||
|
||||
g_warning("No listener with the specified listener id %d",
|
||||
remove_listener);
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid listener_id %d", remove_listener);
|
||||
}
|
||||
}
|
||||
|
||||
static AtkKeyEventStruct *
|
||||
atk_key_event_from_gdk_event_key (GdkEventKey *key)
|
||||
{
|
||||
AtkKeyEventStruct *event = g_new0(AtkKeyEventStruct, 1);
|
||||
switch (key->type) {
|
||||
case GDK_KEY_PRESS:
|
||||
event->type = ATK_KEY_EVENT_PRESS;
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
event->type = ATK_KEY_EVENT_RELEASE;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
event->state = key->state;
|
||||
event->keyval = key->keyval;
|
||||
event->length = key->length;
|
||||
if (key->string && key->string [0] &&
|
||||
(key->state & GDK_CONTROL_MASK ||
|
||||
g_unichar_isgraph (g_utf8_get_char (key->string)))) {
|
||||
event->string = key->string;
|
||||
}
|
||||
else if (key->type == GDK_KEY_PRESS ||
|
||||
key->type == GDK_KEY_RELEASE) {
|
||||
event->string = gdk_keyval_name (key->keyval);
|
||||
}
|
||||
event->keycode = key->hardware_keycode;
|
||||
event->timestamp = key->time;
|
||||
|
||||
MAI_LOG_DEBUG(("MaiKey:\tsym %u\n\tmods %x\n\tcode %u\n\ttime %lx\n",
|
||||
(unsigned int) event->keyval,
|
||||
(unsigned int) event->state,
|
||||
(unsigned int) event->keycode,
|
||||
(unsigned long int) event->timestamp));
|
||||
return event;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_hf(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
MaiKeyEventInfo *info = (MaiKeyEventInfo *)data;
|
||||
AtkKeySnoopFuncPointer atkKeySnoop;
|
||||
atkKeySnoop.data = value;
|
||||
return (atkKeySnoop.func_ptr)(info->key_event, info->func_data) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
insert_hf(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
GHashTable *new_table = (GHashTable *) data;
|
||||
g_hash_table_insert (new_table, key, value);
|
||||
}
|
||||
|
||||
static gint
|
||||
mai_key_snooper(GtkWidget *the_widget, GdkEventKey *event, gpointer func_data)
|
||||
{
|
||||
/* notify each AtkKeySnoopFunc in turn... */
|
||||
|
||||
MaiKeyEventInfo *info = g_new0(MaiKeyEventInfo, 1);
|
||||
gint consumed = 0;
|
||||
if (sKey_listener_list) {
|
||||
GHashTable *new_hash = g_hash_table_new(NULL, NULL);
|
||||
g_hash_table_foreach (sKey_listener_list, insert_hf, new_hash);
|
||||
info->key_event = atk_key_event_from_gdk_event_key (event);
|
||||
info->func_data = func_data;
|
||||
consumed = g_hash_table_foreach_steal (new_hash, notify_hf, info);
|
||||
g_hash_table_destroy (new_hash);
|
||||
g_free(info->key_event);
|
||||
}
|
||||
g_free(info);
|
||||
return (consumed ? 1 : 0);
|
||||
}
|
||||
|
||||
static guint
|
||||
mai_util_add_key_event_listener (AtkKeySnoopFunc listener,
|
||||
gpointer data)
|
||||
{
|
||||
NS_ENSURE_TRUE(listener, 0);
|
||||
|
||||
static guint key=0;
|
||||
|
||||
if (!sKey_listener_list) {
|
||||
sKey_listener_list = g_hash_table_new(NULL, NULL);
|
||||
sKey_snooper_id = gtk_key_snooper_install(mai_key_snooper, data);
|
||||
}
|
||||
AtkKeySnoopFuncPointer atkKeySnoop;
|
||||
atkKeySnoop.func_ptr = listener;
|
||||
g_hash_table_insert(sKey_listener_list, GUINT_TO_POINTER (key++),
|
||||
atkKeySnoop.data);
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
mai_util_remove_key_event_listener (guint remove_listener)
|
||||
{
|
||||
if (!sKey_listener_list) {
|
||||
// atk-bridge is initialized with gail (e.g. yelp)
|
||||
// try gail_remove_key_event_listener
|
||||
return gail_remove_key_event_listener(remove_listener);
|
||||
}
|
||||
|
||||
g_hash_table_remove(sKey_listener_list, GUINT_TO_POINTER (remove_listener));
|
||||
if (g_hash_table_size(sKey_listener_list) == 0) {
|
||||
gtk_key_snooper_remove(sKey_snooper_id);
|
||||
}
|
||||
}
|
||||
|
||||
AtkObject*
|
||||
mai_util_get_root(void)
|
||||
{
|
||||
ApplicationAccessible* app = ApplicationAcc();
|
||||
if (app)
|
||||
return app->GetAtkObject();
|
||||
|
||||
// We've shutdown, try to use gail instead
|
||||
// (to avoid assert in spi_atk_tidy_windows())
|
||||
// XXX tbsaunde then why didn't we replace the gail atk_util impl?
|
||||
if (gail_get_root)
|
||||
return gail_get_root();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
G_CONST_RETURN gchar *
|
||||
mai_util_get_toolkit_name(void)
|
||||
{
|
||||
return MAI_NAME;
|
||||
}
|
||||
|
||||
G_CONST_RETURN gchar *
|
||||
mai_util_get_toolkit_version(void)
|
||||
{
|
||||
return MAI_VERSION;
|
||||
}
|
||||
|
||||
void
|
||||
_listener_info_destroy(gpointer data)
|
||||
{
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
guint
|
||||
add_listener (GSignalEmissionHook listener,
|
||||
const gchar *object_type,
|
||||
const gchar *signal,
|
||||
const gchar *hook_data,
|
||||
guint gail_listenerid)
|
||||
{
|
||||
GType type;
|
||||
guint signal_id;
|
||||
gint rc = 0;
|
||||
|
||||
type = g_type_from_name(object_type);
|
||||
if (type) {
|
||||
signal_id = g_signal_lookup(signal, type);
|
||||
if (signal_id > 0) {
|
||||
MaiUtilListenerInfo *listener_info;
|
||||
|
||||
rc = sListener_idx;
|
||||
|
||||
listener_info = (MaiUtilListenerInfo *)
|
||||
g_malloc(sizeof(MaiUtilListenerInfo));
|
||||
listener_info->key = sListener_idx;
|
||||
listener_info->hook_id =
|
||||
g_signal_add_emission_hook(signal_id, 0, listener,
|
||||
g_strdup(hook_data),
|
||||
(GDestroyNotify)g_free);
|
||||
listener_info->signal_id = signal_id;
|
||||
listener_info->gail_listenerid = gail_listenerid;
|
||||
|
||||
g_hash_table_insert(sListener_list, &(listener_info->key),
|
||||
listener_info);
|
||||
sListener_idx++;
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid signal type %s\n", signal);
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid object type %s\n", object_type);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static nsresult LoadGtkModule(GnomeAccessibilityModule& aModule);
|
||||
|
||||
static gboolean toplevel_event_watcher(GSignalInvocationHint*, guint,
|
||||
|
@ -519,16 +78,11 @@ static gboolean toplevel_event_watcher(GSignalInvocationHint*, guint,
|
|||
ApplicationAccessibleWrap::ApplicationAccessibleWrap():
|
||||
ApplicationAccessible()
|
||||
{
|
||||
MAI_LOG_DEBUG(("======Create AppRootAcc=%p\n", (void*)this));
|
||||
|
||||
if (ShouldA11yBeEnabled()) {
|
||||
// Load and initialize gail library.
|
||||
nsresult rv = LoadGtkModule(sGail);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (NS_SUCCEEDED(rv))
|
||||
(*sGail.init)();
|
||||
} else {
|
||||
MAI_LOG_DEBUG(("Fail to load lib: %s\n", sGail.libName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -544,15 +98,13 @@ nsAccessNodeWrap::InitAccessibility()
|
|||
return;
|
||||
|
||||
// Initialize the MAI Utility class, it will overwrite gail_util.
|
||||
g_type_class_unref(g_type_class_ref(MAI_TYPE_UTIL));
|
||||
g_type_class_unref(g_type_class_ref(mai_util_get_type()));
|
||||
|
||||
// Init atk-bridge now
|
||||
PR_SetEnv("NO_AT_BRIDGE=0");
|
||||
nsresult rv = LoadGtkModule(sAtkBridge);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
(*sAtkBridge.init)();
|
||||
} else {
|
||||
MAI_LOG_DEBUG(("Fail to load lib: %s\n", sAtkBridge.libName));
|
||||
}
|
||||
|
||||
if (!sToplevel_event_hook_added) {
|
||||
|
@ -573,7 +125,6 @@ nsAccessNodeWrap::InitAccessibility()
|
|||
|
||||
ApplicationAccessibleWrap::~ApplicationAccessibleWrap()
|
||||
{
|
||||
MAI_LOG_DEBUG(("======Destory AppRootAcc=%p\n", (void*)this));
|
||||
AccessibleWrap::ShutdownAtkObject();
|
||||
}
|
||||
|
||||
|
@ -788,9 +339,6 @@ LoadGtkModule(GnomeAccessibilityModule& aModule)
|
|||
NS_ENSURE_ARG(aModule.libName);
|
||||
|
||||
if (!(aModule.lib = PR_LoadLibrary(aModule.libName))) {
|
||||
|
||||
MAI_LOG_DEBUG(("Fail to load lib: %s in default path\n", aModule.libName));
|
||||
|
||||
//try to load the module with "gtk-2.0/modules" appended
|
||||
char *curLibPath = PR_GetLibraryPath();
|
||||
nsAutoCString libPath(curLibPath);
|
||||
|
@ -799,7 +347,6 @@ LoadGtkModule(GnomeAccessibilityModule& aModule)
|
|||
#else
|
||||
libPath.Append(":/usr/lib");
|
||||
#endif
|
||||
MAI_LOG_DEBUG(("Current Lib path=%s\n", libPath.get()));
|
||||
PR_FreeLibraryName(curLibPath);
|
||||
|
||||
int16_t loc1 = 0, loc2 = 0;
|
||||
|
@ -814,17 +361,14 @@ LoadGtkModule(GnomeAccessibilityModule& aModule)
|
|||
sub.Append("/gtk-2.0/modules/");
|
||||
sub.Append(aModule.libName);
|
||||
aModule.lib = PR_LoadLibrary(sub.get());
|
||||
if (aModule.lib) {
|
||||
MAI_LOG_DEBUG(("Ok, load %s from %s\n", aModule.libName, sub.get()));
|
||||
if (aModule.lib)
|
||||
break;
|
||||
}
|
||||
|
||||
loc1 = loc2+1;
|
||||
}
|
||||
if (!aModule.lib) {
|
||||
MAI_LOG_DEBUG(("Fail to load %s\n", aModule.libName));
|
||||
if (!aModule.lib)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
//we have loaded the library, try to get the function ptrs
|
||||
if (!(aModule.init = PR_FindFunctionSymbol(aModule.lib,
|
||||
|
@ -833,9 +377,6 @@ LoadGtkModule(GnomeAccessibilityModule& aModule)
|
|||
aModule.shutdownName))) {
|
||||
|
||||
//fail, :(
|
||||
MAI_LOG_DEBUG(("Fail to find symbol %s in %s",
|
||||
aModule.init ? aModule.shutdownName : aModule.initName,
|
||||
aModule.libName));
|
||||
PR_UnloadLibrary(aModule.lib);
|
||||
aModule.lib = NULL;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -17,6 +17,8 @@ class AccessibleWrap;
|
|||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
struct MaiUtilClass;
|
||||
|
||||
extern "C" {
|
||||
void actionInterfaceInitCB(AtkActionIface* aIface);
|
||||
void componentInterfaceInitCB(AtkComponentIface* aIface);
|
||||
|
|
|
@ -34,6 +34,7 @@ CPPSRCS = \
|
|||
nsMaiInterfaceDocument.cpp \
|
||||
nsMaiInterfaceImage.cpp \
|
||||
RootAccessibleWrap.cpp \
|
||||
UtilInterface.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
|
|
@ -0,0 +1,404 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ApplicationAccessibleWrap.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
#include "nsMai.h"
|
||||
|
||||
#include <atk/atk.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
typedef AtkUtil MaiUtil;
|
||||
typedef AtkUtilClass MaiUtilClass;
|
||||
|
||||
#define MAI_VERSION MOZILLA_VERSION
|
||||
#define MAI_NAME "Gecko"
|
||||
|
||||
extern "C" {
|
||||
static guint (*gail_add_global_event_listener)(GSignalEmissionHook listener,
|
||||
const gchar* event_type);
|
||||
static void (*gail_remove_global_event_listener) (guint remove_listener);
|
||||
static void (*gail_remove_key_event_listener) (guint remove_listener);
|
||||
static AtkObject* (*gail_get_root)();
|
||||
}
|
||||
|
||||
struct MaiUtilListenerInfo
|
||||
{
|
||||
gint key;
|
||||
guint signal_id;
|
||||
gulong hook_id;
|
||||
// For window create/destory/minimize/maximize/restore/activate/deactivate
|
||||
// events, we'll chain gail_util's add/remove_global_event_listener.
|
||||
// So we store the listenerid returned by gail's add_global_event_listener
|
||||
// in this structure to call gail's remove_global_event_listener later.
|
||||
guint gail_listenerid;
|
||||
};
|
||||
|
||||
static GHashTable* sListener_list = NULL;
|
||||
static gint sListener_idx = 1;
|
||||
|
||||
extern "C" {
|
||||
static guint
|
||||
add_listener (GSignalEmissionHook listener,
|
||||
const gchar *object_type,
|
||||
const gchar *signal,
|
||||
const gchar *hook_data,
|
||||
guint gail_listenerid = 0)
|
||||
{
|
||||
GType type;
|
||||
guint signal_id;
|
||||
gint rc = 0;
|
||||
|
||||
type = g_type_from_name(object_type);
|
||||
if (type) {
|
||||
signal_id = g_signal_lookup(signal, type);
|
||||
if (signal_id > 0) {
|
||||
MaiUtilListenerInfo *listener_info;
|
||||
|
||||
rc = sListener_idx;
|
||||
|
||||
listener_info = (MaiUtilListenerInfo *)
|
||||
g_malloc(sizeof(MaiUtilListenerInfo));
|
||||
listener_info->key = sListener_idx;
|
||||
listener_info->hook_id =
|
||||
g_signal_add_emission_hook(signal_id, 0, listener,
|
||||
g_strdup(hook_data),
|
||||
(GDestroyNotify)g_free);
|
||||
listener_info->signal_id = signal_id;
|
||||
listener_info->gail_listenerid = gail_listenerid;
|
||||
|
||||
g_hash_table_insert(sListener_list, &(listener_info->key),
|
||||
listener_info);
|
||||
sListener_idx++;
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid signal type %s\n", signal);
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid object type %s\n", object_type);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static guint
|
||||
mai_util_add_global_event_listener(GSignalEmissionHook listener,
|
||||
const gchar *event_type)
|
||||
{
|
||||
guint rc = 0;
|
||||
gchar **split_string;
|
||||
|
||||
split_string = g_strsplit (event_type, ":", 3);
|
||||
|
||||
if (split_string) {
|
||||
if (!strcmp ("window", split_string[0])) {
|
||||
guint gail_listenerid = 0;
|
||||
if (gail_add_global_event_listener) {
|
||||
// call gail's function to track gtk native window events
|
||||
gail_listenerid =
|
||||
gail_add_global_event_listener(listener, event_type);
|
||||
}
|
||||
|
||||
rc = add_listener (listener, "MaiAtkObject", split_string[1],
|
||||
event_type, gail_listenerid);
|
||||
}
|
||||
else {
|
||||
rc = add_listener (listener, split_string[1], split_string[2],
|
||||
event_type);
|
||||
}
|
||||
g_strfreev(split_string);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
mai_util_remove_global_event_listener(guint remove_listener)
|
||||
{
|
||||
if (remove_listener > 0) {
|
||||
MaiUtilListenerInfo *listener_info;
|
||||
gint tmp_idx = remove_listener;
|
||||
|
||||
listener_info = (MaiUtilListenerInfo *)
|
||||
g_hash_table_lookup(sListener_list, &tmp_idx);
|
||||
|
||||
if (listener_info != NULL) {
|
||||
if (gail_remove_global_event_listener &&
|
||||
listener_info->gail_listenerid) {
|
||||
gail_remove_global_event_listener(listener_info->gail_listenerid);
|
||||
}
|
||||
|
||||
/* Hook id of 0 and signal id of 0 are invalid */
|
||||
if (listener_info->hook_id != 0 && listener_info->signal_id != 0) {
|
||||
/* Remove the emission hook */
|
||||
g_signal_remove_emission_hook(listener_info->signal_id,
|
||||
listener_info->hook_id);
|
||||
|
||||
/* Remove the element from the hash */
|
||||
g_hash_table_remove(sListener_list, &tmp_idx);
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid listener hook_id %ld or signal_id %d\n",
|
||||
listener_info->hook_id, listener_info->signal_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// atk-bridge is initialized with gail (e.g. yelp)
|
||||
// try gail_remove_global_event_listener
|
||||
if (gail_remove_global_event_listener) {
|
||||
return gail_remove_global_event_listener(remove_listener);
|
||||
}
|
||||
|
||||
g_warning("No listener with the specified listener id %d",
|
||||
remove_listener);
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_warning("Invalid listener_id %d", remove_listener);
|
||||
}
|
||||
}
|
||||
|
||||
static AtkKeyEventStruct *
|
||||
atk_key_event_from_gdk_event_key (GdkEventKey *key)
|
||||
{
|
||||
AtkKeyEventStruct *event = g_new0(AtkKeyEventStruct, 1);
|
||||
switch (key->type) {
|
||||
case GDK_KEY_PRESS:
|
||||
event->type = ATK_KEY_EVENT_PRESS;
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
event->type = ATK_KEY_EVENT_RELEASE;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
event->state = key->state;
|
||||
event->keyval = key->keyval;
|
||||
event->length = key->length;
|
||||
if (key->string && key->string [0] &&
|
||||
(key->state & GDK_CONTROL_MASK ||
|
||||
g_unichar_isgraph (g_utf8_get_char (key->string)))) {
|
||||
event->string = key->string;
|
||||
}
|
||||
else if (key->type == GDK_KEY_PRESS ||
|
||||
key->type == GDK_KEY_RELEASE) {
|
||||
event->string = gdk_keyval_name (key->keyval);
|
||||
}
|
||||
event->keycode = key->hardware_keycode;
|
||||
event->timestamp = key->time;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
struct MaiKeyEventInfo
|
||||
{
|
||||
AtkKeyEventStruct *key_event;
|
||||
gpointer func_data;
|
||||
};
|
||||
|
||||
union AtkKeySnoopFuncPointer
|
||||
{
|
||||
AtkKeySnoopFunc func_ptr;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
notify_hf(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
MaiKeyEventInfo *info = (MaiKeyEventInfo *)data;
|
||||
AtkKeySnoopFuncPointer atkKeySnoop;
|
||||
atkKeySnoop.data = value;
|
||||
return (atkKeySnoop.func_ptr)(info->key_event, info->func_data) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
insert_hf(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
GHashTable *new_table = (GHashTable *) data;
|
||||
g_hash_table_insert (new_table, key, value);
|
||||
}
|
||||
|
||||
static GHashTable* sKey_listener_list = NULL;
|
||||
|
||||
static gint
|
||||
mai_key_snooper(GtkWidget *the_widget, GdkEventKey *event, gpointer func_data)
|
||||
{
|
||||
/* notify each AtkKeySnoopFunc in turn... */
|
||||
|
||||
MaiKeyEventInfo *info = g_new0(MaiKeyEventInfo, 1);
|
||||
gint consumed = 0;
|
||||
if (sKey_listener_list) {
|
||||
GHashTable *new_hash = g_hash_table_new(NULL, NULL);
|
||||
g_hash_table_foreach (sKey_listener_list, insert_hf, new_hash);
|
||||
info->key_event = atk_key_event_from_gdk_event_key (event);
|
||||
info->func_data = func_data;
|
||||
consumed = g_hash_table_foreach_steal (new_hash, notify_hf, info);
|
||||
g_hash_table_destroy (new_hash);
|
||||
g_free(info->key_event);
|
||||
}
|
||||
g_free(info);
|
||||
return (consumed ? 1 : 0);
|
||||
}
|
||||
|
||||
static guint sKey_snooper_id = 0;
|
||||
|
||||
static guint
|
||||
mai_util_add_key_event_listener (AtkKeySnoopFunc listener,
|
||||
gpointer data)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!listener))
|
||||
return 0;
|
||||
|
||||
static guint key=0;
|
||||
|
||||
if (!sKey_listener_list) {
|
||||
sKey_listener_list = g_hash_table_new(NULL, NULL);
|
||||
sKey_snooper_id = gtk_key_snooper_install(mai_key_snooper, data);
|
||||
}
|
||||
AtkKeySnoopFuncPointer atkKeySnoop;
|
||||
atkKeySnoop.func_ptr = listener;
|
||||
g_hash_table_insert(sKey_listener_list, GUINT_TO_POINTER (key++),
|
||||
atkKeySnoop.data);
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
mai_util_remove_key_event_listener (guint remove_listener)
|
||||
{
|
||||
if (!sKey_listener_list) {
|
||||
// atk-bridge is initialized with gail (e.g. yelp)
|
||||
// try gail_remove_key_event_listener
|
||||
return gail_remove_key_event_listener(remove_listener);
|
||||
}
|
||||
|
||||
g_hash_table_remove(sKey_listener_list, GUINT_TO_POINTER (remove_listener));
|
||||
if (g_hash_table_size(sKey_listener_list) == 0) {
|
||||
gtk_key_snooper_remove(sKey_snooper_id);
|
||||
}
|
||||
}
|
||||
|
||||
static AtkObject*
|
||||
mai_util_get_root()
|
||||
{
|
||||
ApplicationAccessible* app = ApplicationAcc();
|
||||
if (app)
|
||||
return app->GetAtkObject();
|
||||
|
||||
// We've shutdown, try to use gail instead
|
||||
// (to avoid assert in spi_atk_tidy_windows())
|
||||
// XXX tbsaunde then why didn't we replace the gail atk_util impl?
|
||||
if (gail_get_root)
|
||||
return gail_get_root();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
mai_util_get_toolkit_name()
|
||||
{
|
||||
return MAI_NAME;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
mai_util_get_toolkit_version()
|
||||
{
|
||||
return MAI_VERSION;
|
||||
}
|
||||
|
||||
static void
|
||||
_listener_info_destroy(gpointer data)
|
||||
{
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
window_added (AtkObject *atk_obj,
|
||||
guint index,
|
||||
AtkObject *child)
|
||||
{
|
||||
if (!IS_MAI_OBJECT(child))
|
||||
return;
|
||||
|
||||
static guint id = g_signal_lookup ("create", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit (child, id, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
window_removed (AtkObject *atk_obj,
|
||||
guint index,
|
||||
AtkObject *child)
|
||||
{
|
||||
if (!IS_MAI_OBJECT(child))
|
||||
return;
|
||||
|
||||
static guint id = g_signal_lookup ("destroy", MAI_TYPE_ATK_OBJECT);
|
||||
g_signal_emit (child, id, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
UtilInterfaceInit(MaiUtilClass* klass)
|
||||
{
|
||||
AtkUtilClass *atk_class;
|
||||
gpointer data;
|
||||
|
||||
data = g_type_class_peek(ATK_TYPE_UTIL);
|
||||
atk_class = ATK_UTIL_CLASS(data);
|
||||
|
||||
// save gail function pointer
|
||||
gail_add_global_event_listener = atk_class->add_global_event_listener;
|
||||
gail_remove_global_event_listener = atk_class->remove_global_event_listener;
|
||||
gail_remove_key_event_listener = atk_class->remove_key_event_listener;
|
||||
gail_get_root = atk_class->get_root;
|
||||
|
||||
atk_class->add_global_event_listener =
|
||||
mai_util_add_global_event_listener;
|
||||
atk_class->remove_global_event_listener =
|
||||
mai_util_remove_global_event_listener;
|
||||
atk_class->add_key_event_listener = mai_util_add_key_event_listener;
|
||||
atk_class->remove_key_event_listener = mai_util_remove_key_event_listener;
|
||||
atk_class->get_root = mai_util_get_root;
|
||||
atk_class->get_toolkit_name = mai_util_get_toolkit_name;
|
||||
atk_class->get_toolkit_version = mai_util_get_toolkit_version;
|
||||
|
||||
sListener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
|
||||
_listener_info_destroy);
|
||||
// Keep track of added/removed windows.
|
||||
AtkObject *root = atk_get_root ();
|
||||
g_signal_connect (root, "children-changed::add", (GCallback) window_added, NULL);
|
||||
g_signal_connect (root, "children-changed::remove", (GCallback) window_removed, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
GType
|
||||
mai_util_get_type()
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (!type) {
|
||||
static const GTypeInfo tinfo = {
|
||||
sizeof(MaiUtilClass),
|
||||
(GBaseInitFunc) NULL, /* base init */
|
||||
(GBaseFinalizeFunc) NULL, /* base finalize */
|
||||
(GClassInitFunc) UtilInterfaceInit, /* class init */
|
||||
(GClassFinalizeFunc) NULL, /* class finalize */
|
||||
NULL, /* class data */
|
||||
sizeof(MaiUtil), /* instance size */
|
||||
0, /* nb preallocs */
|
||||
(GInstanceInitFunc) NULL, /* instance init */
|
||||
NULL /* value table */
|
||||
};
|
||||
|
||||
type = g_type_register_static(ATK_TYPE_UTIL,
|
||||
"MaiUtil", &tinfo, GTypeFlags(0));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
|
@ -13,25 +13,6 @@
|
|||
|
||||
#include "AccessibleWrap.h"
|
||||
|
||||
extern PRLogModuleInfo *gMaiLog;
|
||||
|
||||
#ifdef MAI_LOGGING
|
||||
#define MAI_LOG(level, args) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (!gMaiLog) { \
|
||||
gMaiLog = PR_NewLogModule("Mai"); \
|
||||
PR_ASSERT(gMaiLog); \
|
||||
} \
|
||||
PR_LOG(gMaiLog, (level), args); \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define MAI_LOG(level, args)
|
||||
#endif
|
||||
|
||||
#define MAI_LOG_DEBUG(args) MAI_LOG(PR_LOG_DEBUG, args)
|
||||
#define MAI_LOG_WARNING(args) MAI_LOG(PR_LOG_WARNING, args)
|
||||
#define MAI_LOG_ERROR(args) MAI_LOG(PR_LOG_ERROR, args)
|
||||
|
||||
#define MAI_TYPE_ATK_OBJECT (mai_atk_object_get_type ())
|
||||
#define MAI_ATK_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
MAI_TYPE_ATK_OBJECT, MaiAtkObject))
|
||||
|
@ -46,6 +27,7 @@ PR_END_MACRO
|
|||
MAI_TYPE_ATK_OBJECT, \
|
||||
MaiAtkObjectClass))
|
||||
GType mai_atk_object_get_type(void);
|
||||
GType mai_util_get_type();
|
||||
mozilla::a11y::AccessibleWrap* GetAccessibleWrap(AtkObject* aAtkObj);
|
||||
|
||||
#endif /* __NS_MAI_H__ */
|
||||
|
|
|
@ -26,8 +26,6 @@ setTextContentsCB(AtkEditableText *aText, const gchar *aString)
|
|||
if (!text || !text->IsTextRole())
|
||||
return;
|
||||
|
||||
MAI_LOG_DEBUG(("EditableText: setTextContentsCB, aString=%s", aString));
|
||||
|
||||
NS_ConvertUTF8toUTF16 strContent(aString);
|
||||
text->SetTextContents(strContent);
|
||||
}
|
||||
|
@ -46,9 +44,6 @@ insertTextCB(AtkEditableText *aText,
|
|||
|
||||
NS_ConvertUTF8toUTF16 strContent(aString, aLength);
|
||||
text->InsertText(strContent, *aPosition);
|
||||
|
||||
MAI_LOG_DEBUG(("EditableText: insert aString=%s, aLength=%d, aPosition=%d",
|
||||
aString, aLength, *aPosition));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -62,8 +57,6 @@ copyTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
|
|||
if (!text || !text->IsTextRole())
|
||||
return;
|
||||
|
||||
MAI_LOG_DEBUG(("EditableText: copyTextCB, aStartPos=%d, aEndPos=%d",
|
||||
aStartPos, aEndPos));
|
||||
text->CopyText(aStartPos, aEndPos);
|
||||
}
|
||||
|
||||
|
@ -78,8 +71,6 @@ cutTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
|
|||
if (!text || !text->IsTextRole())
|
||||
return;
|
||||
|
||||
MAI_LOG_DEBUG(("EditableText: cutTextCB, aStartPos=%d, aEndPos=%d",
|
||||
aStartPos, aEndPos));
|
||||
text->CutText(aStartPos, aEndPos);
|
||||
}
|
||||
|
||||
|
@ -94,8 +85,6 @@ deleteTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
|
|||
if (!text || !text->IsTextRole())
|
||||
return;
|
||||
|
||||
MAI_LOG_DEBUG(("EditableText: deleteTextCB, aStartPos=%d, aEndPos=%d",
|
||||
aStartPos, aEndPos));
|
||||
text->DeleteText(aStartPos, aEndPos);
|
||||
}
|
||||
|
||||
|
@ -110,7 +99,6 @@ pasteTextCB(AtkEditableText *aText, gint aPosition)
|
|||
if (!text || !text->IsTextRole())
|
||||
return;
|
||||
|
||||
MAI_LOG_DEBUG(("EditableText: pasteTextCB, aPosition=%d", aPosition));
|
||||
text->PasteText(aPosition);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||
INSTALL_TARGETS += ACCESSFU
|
||||
|
||||
ACCESSFU_FILES := \
|
||||
AccessFu.css \
|
||||
AccessFu.jsm \
|
||||
content-script.js \
|
||||
EventManager.jsm \
|
||||
jar.mn \
|
||||
Makefile.in \
|
||||
|
|
|
@ -64,36 +64,32 @@ SettingsListener.observe('audio.volume.master', 0.5, function(value) {
|
|||
audioManager.masterVolume = Math.max(0.0, Math.min(value, 1.0));
|
||||
});
|
||||
|
||||
let audioSettings = [];
|
||||
let audioChannelSettings = [];
|
||||
|
||||
if ("nsIAudioManager" in Ci) {
|
||||
const nsIAudioManager = Ci.nsIAudioManager;
|
||||
audioSettings = [
|
||||
// settings name, default value, stream type
|
||||
['audio.volume.voice_call', 10, nsIAudioManager.STREAM_TYPE_VOICE_CALL],
|
||||
['audio.volume.system', 15, nsIAudioManager.STREAM_TYPE_SYSTEM],
|
||||
['audio.volume.ring', 7, nsIAudioManager.STREAM_TYPE_RING],
|
||||
['audio.volume.music', 15, nsIAudioManager.STREAM_TYPE_MUSIC],
|
||||
['audio.volume.alarm', 7, nsIAudioManager.STREAM_TYPE_ALARM],
|
||||
['audio.volume.notification', 7, nsIAudioManager.STREAM_TYPE_NOTIFICATION],
|
||||
['audio.volume.bt_sco', 15, nsIAudioManager.STREAM_TYPE_BLUETOOTH_SCO],
|
||||
['audio.volume.enforced_audible', 7, nsIAudioManager.STREAM_TYPE_ENFORCED_AUDIBLE],
|
||||
['audio.volume.dtmf', 15, nsIAudioManager.STREAM_TYPE_DTMF],
|
||||
['audio.volume.tts', 15, nsIAudioManager.STREAM_TYPE_TTS],
|
||||
['audio.volume.fm', 15, nsIAudioManager.STREAM_TYPE_FM],
|
||||
audioChannelSettings = [
|
||||
// settings name, max value, apply to stream types
|
||||
['audio.volume.content', 15, [nsIAudioManager.STREAM_TYPE_SYSTEM, nsIAudioManager.STREAM_TYPE_MUSIC, nsIAudioManager.STREAM_TYPE_FM]],
|
||||
['audio.volume.notification', 15, [nsIAudioManager.STREAM_TYPE_RING, nsIAudioManager.STREAM_TYPE_NOTIFICATION]],
|
||||
['audio.volume.alarm', 15, [nsIAudioManager.STREAM_TYPE_ALARM]],
|
||||
['audio.volume.telephony', 5, [nsIAudioManager.STREAM_TYPE_VOICE_CALL]],
|
||||
['audio.volume.bt_sco', 15, [nsIAudioManager.STREAM_TYPE_BLUETOOTH_SCO]],
|
||||
];
|
||||
}
|
||||
|
||||
for each (let [setting, defaultValue, streamType] in audioSettings) {
|
||||
(function AudioStreamSettings(s, d, t) {
|
||||
SettingsListener.observe(s, d, function(value) {
|
||||
for each (let [setting, maxValue, streamTypes] in audioChannelSettings) {
|
||||
(function AudioStreamSettings(setting, maxValue, streamTypes) {
|
||||
SettingsListener.observe(setting, maxValue, function(value) {
|
||||
let audioManager = Services.audioManager;
|
||||
if (!audioManager)
|
||||
return;
|
||||
|
||||
audioManager.setStreamVolumeIndex(t, Math.min(value, d));
|
||||
for each(let streamType in streamTypes) {
|
||||
audioManager.setStreamVolumeIndex(streamType, Math.min(value, maxValue));
|
||||
}
|
||||
});
|
||||
})(setting, defaultValue, streamType);
|
||||
})(setting, maxValue, streamTypes);
|
||||
}
|
||||
|
||||
// =================== Console ======================
|
||||
|
@ -157,12 +153,14 @@ Components.utils.import('resource://gre/modules/ctypes.jsm');
|
|||
'@mozilla.org/settingsService;1',
|
||||
'nsISettingsService');
|
||||
let lock = gSettingsService.createLock();
|
||||
//MOZ_B2G_VERSION is set in b2g/confvars.sh, and is outputed as a #define value
|
||||
//from configure.in, defaults to 1.0.0 if this value is not exist
|
||||
// MOZ_B2G_VERSION is set in b2g/confvars.sh, and is output as a #define value
|
||||
// from configure.in, defaults to 1.0.0 if this value is not exist.
|
||||
#filter attemptSubstitution
|
||||
let os_version = '@MOZ_B2G_VERSION@';
|
||||
let os_name = '@MOZ_B2G_OS_NAME@';
|
||||
#unfilter attemptSubstitution
|
||||
lock.set('deviceinfo.os', os_version, null, null);
|
||||
lock.set('deviceinfo.software', os_name + ' ' + os_version, null, null);
|
||||
|
||||
let appInfo = Cc["@mozilla.org/xre/app-info;1"]
|
||||
.getService(Ci.nsIXULAppInfo);
|
||||
|
@ -172,8 +170,9 @@ Components.utils.import('resource://gre/modules/ctypes.jsm');
|
|||
let update_channel = Services.prefs.getCharPref('app.update.channel');
|
||||
lock.set('deviceinfo.update_channel', update_channel, null, null);
|
||||
|
||||
//Get the hardware info from android properties
|
||||
let hardware_version = null;
|
||||
// Get the hardware info and firmware revision from device properties.
|
||||
let hardware_info = null;
|
||||
let firmware_revision = null;
|
||||
try {
|
||||
let cutils = ctypes.open('libcutils.so');
|
||||
let cbuf = ctypes.char.array(128)();
|
||||
|
@ -189,12 +188,14 @@ Components.utils.import('resource://gre/modules/ctypes.jsm');
|
|||
c_property_get(key, cbuf, defaultValue);
|
||||
return cbuf.readString();
|
||||
}
|
||||
hardware_version = property_get('ro.hardware');
|
||||
hardware_info = property_get('ro.hardware');
|
||||
firmware_revision = property_get('ro.firmware_revision');
|
||||
cutils.close();
|
||||
} catch(e) {
|
||||
//Error
|
||||
// Error.
|
||||
}
|
||||
lock.set('deviceinfo.hardware', hardware_version, null, null);
|
||||
lock.set('deviceinfo.hardware', hardware_info, null, null);
|
||||
lock.set('deviceinfo.firmware_revision', firmware_revision, null, null);
|
||||
})();
|
||||
|
||||
// =================== Debugger ====================
|
||||
|
|
|
@ -928,6 +928,15 @@ window.addEventListener('ContentStart', function update_onContentStart() {
|
|||
}, "headphones-status-changed", false);
|
||||
})();
|
||||
|
||||
(function audioChannelChangedTracker() {
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
shell.sendChromeEvent({
|
||||
type: 'audio-channel-changed',
|
||||
channel: aData
|
||||
});
|
||||
}, "audio-channel-changed", false);
|
||||
})();
|
||||
|
||||
(function recordingStatusTracker() {
|
||||
let gRecordingActiveCount = 0;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ const Cu = Components.utils;
|
|||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/IdentityUtils.jsm");
|
||||
Cu.import("resource://gre/modules/identity/IdentityUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
|
||||
"resource://gre/modules/identity/MinimalIdentity.jsm");
|
||||
|
|
|
@ -6,14 +6,22 @@
|
|||
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
|
||||
"build_targets": [],
|
||||
"upload_files": [
|
||||
"{workdir}/out/target/product/otoro/*.img",
|
||||
"{objdir}/dist/b2g-update/*.mar",
|
||||
"{objdir}/dist/b2g-*.tar.gz",
|
||||
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
|
||||
"{workdir}/sources.xml"
|
||||
],
|
||||
"zip_files": [
|
||||
["{workdir}/out/target/product/otoro/*.img", "out/target/product/otoro/"],
|
||||
"{workdir}/boot.img",
|
||||
"{workdir}/flash.sh",
|
||||
"{workdir}/load-config.sh",
|
||||
"{workdir}/.config",
|
||||
"{workdir}/sources.xml"
|
||||
],
|
||||
"env": {
|
||||
"VARIANT": "user",
|
||||
"MOZILLA_OFFICIAL": "1",
|
||||
"B2GUPDATER": "1"
|
||||
},
|
||||
"gaia": {
|
||||
|
|
|
@ -4,5 +4,11 @@
|
|||
"digest": "0ccae39ee8910947fe3cf51fa3a45e820d2ff11571f6ccec29d9b3e5ae7f7709c1ad657210fbfea98baadd032c3d6a58e00ddbb2e93acafd751089869a72fed6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gonk.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 4139008,
|
||||
"digest": "b1eac90cebe52708d512bbc293c507da9d93bc8c6a78cbbbd78cc9b7beb2cd335bef9bf8e4bf5a9dc38521f7080d29a743626f9e4af6c42ec211db22dc9d0fda",
|
||||
"algorithm": "sha512",
|
||||
"filename": "boot.img"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../panda/README
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"config_version": 1,
|
||||
"tooltool_manifest": "releng-pandaboard.tt",
|
||||
"mock_target": "mozilla-centos6-i386",
|
||||
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
|
||||
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
|
||||
"build_targets": ["boottarball", "systemtarball", "userdatatarball"],
|
||||
"upload_files": [
|
||||
"{workdir}/out/target/product/panda/*.tar.bz2",
|
||||
"{objdir}/dist/b2g-update/*.mar",
|
||||
"{objdir}/dist/b2g-*.tar.gz",
|
||||
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
|
||||
"{srcdir}/b2g/config/panda/README",
|
||||
"{workdir}/sources.xml"
|
||||
],
|
||||
"gaia": {
|
||||
"vcs": "hgtool",
|
||||
"repo": "http://hg.mozilla.org/integration/gaia-central",
|
||||
"l10n": {
|
||||
"vcs": "hgtool",
|
||||
"root": "http://hg.mozilla.org/gaia-l10n"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
../panda/releng-pandaboard.tt
|
|
@ -0,0 +1 @@
|
|||
../panda/sources.xml
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r168596"
|
||||
"clang_version": "r169139"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 56147341,
|
||||
"digest": "4baed5cbe0189a509b6a328ee35ee488250677f8ea149e6d01af74c7a4a27c898a4112f78af57b33a4e788b2947813b65ab0922e06b67bd504878803dab44f5c",
|
||||
"size": 56158651,
|
||||
"digest": "38d718f20a8fa9218e22ade312e724e6c9cdd7c6650e023cfdc21b5505fe7aa3743ae41c0abd717a1bbccec4c4271be2fa82d0e2f96c91e693d70e33b4dc00d6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -6,14 +6,22 @@
|
|||
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
|
||||
"build_targets": [],
|
||||
"upload_files": [
|
||||
"{workdir}/out/target/product/unagi/*.img",
|
||||
"{objdir}/dist/b2g-update/*.mar",
|
||||
"{objdir}/dist/b2g-*.tar.gz",
|
||||
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
|
||||
"{workdir}/sources.xml"
|
||||
],
|
||||
"zip_files": [
|
||||
["{workdir}/out/target/product/unagi/*.img", "out/target/product/unagi/"],
|
||||
"{workdir}/boot.img",
|
||||
"{workdir}/flash.sh",
|
||||
"{workdir}/load-config.sh",
|
||||
"{workdir}/.config",
|
||||
"{workdir}/sources.xml"
|
||||
],
|
||||
"env": {
|
||||
"VARIANT": "user",
|
||||
"MOZILLA_OFFICIAL": "1",
|
||||
"B2GUPDATER": "1"
|
||||
},
|
||||
"gaia": {
|
||||
|
|
|
@ -4,5 +4,11 @@
|
|||
"digest": "553e88831f0760ef8de039a037c91499ff9334691f0532835c73a44352750a4911752cf0d5346f5e023f64b2351ed7f49a2a833c27538ddde59ad505f50ab063",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gonk.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 8859648,
|
||||
"digest": "05d4a99e0f36cd91d1b10a2b558979ea776e9a7e03b8a921af3b0bfc62e2d96cf4faa20586c39885b6f8b25089fe07726794620a3b18c4826a2f71e29d90a8ef",
|
||||
"algorithm": "sha512",
|
||||
"filename": "boot.img"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -11,6 +11,7 @@ MOZ_APP_UA_NAME=Firefox
|
|||
MOZ_UA_OS_AGNOSTIC=1
|
||||
|
||||
MOZ_B2G_VERSION=1.0.0-prerelease
|
||||
MOZ_B2G_OS_NAME=Boot2Gecko
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
|
||||
MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
|
||||
|
|
|
@ -27,12 +27,6 @@
|
|||
label="&newNavigatorCmd.label;"
|
||||
command="cmd_newNavigator"
|
||||
key="key_newNavigator"/>
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
<menuitem id="appmenu_newPrivateWindow"
|
||||
label="&newPrivateWindow.label;"
|
||||
command="Tools:PrivateBrowsing"
|
||||
key="key_privatebrowsing"/>
|
||||
#endif
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenu_openFile"
|
||||
label="&openFileCmd.label;"
|
||||
|
@ -40,7 +34,13 @@
|
|||
key="openFileKb"/>
|
||||
</menupopup>
|
||||
</splitmenu>
|
||||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
<menuitem id="appmenu_newPrivateWindow"
|
||||
class="menuitem-iconic menuitem-iconic-tooltip"
|
||||
label="&newPrivateWindow.label;"
|
||||
command="Tools:PrivateBrowsing"
|
||||
key="key_privatebrowsing"/>
|
||||
#else
|
||||
<menuitem id="appmenu_privateBrowsing"
|
||||
class="menuitem-iconic menuitem-iconic-tooltip"
|
||||
label="&privateBrowsingCmd.start.label;"
|
||||
|
|
|
@ -27,7 +27,6 @@ let SocialUI = {
|
|||
SocialChatBar.update();
|
||||
});
|
||||
|
||||
this.updateActiveBroadcaster();
|
||||
Social.init(this._providerReady.bind(this));
|
||||
},
|
||||
|
||||
|
@ -119,6 +118,7 @@ let SocialUI = {
|
|||
SocialShareButton.init();
|
||||
SocialSidebar.init();
|
||||
SocialMenu.populate();
|
||||
this.updateActiveBroadcaster();
|
||||
},
|
||||
|
||||
updateToggleCommand: function SocialUI_updateToggleCommand() {
|
||||
|
|
|
@ -16,7 +16,6 @@ var gPrevCharset = null;
|
|||
var gProxyFavIcon = null;
|
||||
var gLastValidURLStr = "";
|
||||
var gInPrintPreviewMode = false;
|
||||
var gDownloadMgr = null;
|
||||
var gContextMenu = null; // nsContextMenu instance
|
||||
var gStartupRan = false;
|
||||
|
||||
|
@ -1339,8 +1338,7 @@ var gBrowserInit = {
|
|||
// If the user manually opens the download manager before the timeout, the
|
||||
// downloads will start right away, and getting the service again won't hurt.
|
||||
setTimeout(function() {
|
||||
gDownloadMgr = Cc["@mozilla.org/download-manager;1"].
|
||||
getService(Ci.nsIDownloadManager);
|
||||
Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (Win7Features) {
|
||||
|
@ -6871,140 +6869,6 @@ var gIdentityHandler = {
|
|||
}
|
||||
};
|
||||
|
||||
let DownloadMonitorPanel = {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadMonitorPanel Member Variables
|
||||
|
||||
_panel: null,
|
||||
_activeStr: null,
|
||||
_pausedStr: null,
|
||||
_lastTime: Infinity,
|
||||
_listening: false,
|
||||
|
||||
get DownloadUtils() {
|
||||
delete this.DownloadUtils;
|
||||
Cu.import("resource://gre/modules/DownloadUtils.jsm", this);
|
||||
return this.DownloadUtils;
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadMonitorPanel Public Methods
|
||||
|
||||
/**
|
||||
* Initialize the status panel and member variables
|
||||
*/
|
||||
init: function DMP_init() {
|
||||
// Initialize "private" member variables
|
||||
this._panel = document.getElementById("download-monitor");
|
||||
|
||||
// Cache the status strings
|
||||
this._activeStr = gNavigatorBundle.getString("activeDownloads1");
|
||||
this._pausedStr = gNavigatorBundle.getString("pausedDownloads1");
|
||||
|
||||
gDownloadMgr.addListener(this);
|
||||
this._listening = true;
|
||||
|
||||
this.updateStatus();
|
||||
},
|
||||
|
||||
uninit: function DMP_uninit() {
|
||||
if (this._listening)
|
||||
gDownloadMgr.removeListener(this);
|
||||
},
|
||||
|
||||
inited: function DMP_inited() {
|
||||
return this._panel != null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update status based on the number of active and paused downloads
|
||||
*/
|
||||
updateStatus: function DMP_updateStatus() {
|
||||
if (!this.inited())
|
||||
return;
|
||||
|
||||
let numActive = gDownloadMgr.activeDownloadCount;
|
||||
|
||||
// Hide the panel and reset the "last time" if there's no downloads
|
||||
if (numActive == 0) {
|
||||
this._panel.hidden = true;
|
||||
this._lastTime = Infinity;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the download with the longest remaining time
|
||||
let numPaused = 0;
|
||||
let maxTime = -Infinity;
|
||||
let dls = gDownloadMgr.activeDownloads;
|
||||
while (dls.hasMoreElements()) {
|
||||
let dl = dls.getNext();
|
||||
if (dl.state == gDownloadMgr.DOWNLOAD_DOWNLOADING) {
|
||||
// Figure out if this download takes longer
|
||||
if (dl.speed > 0 && dl.size > 0)
|
||||
maxTime = Math.max(maxTime, (dl.size - dl.amountTransferred) / dl.speed);
|
||||
else
|
||||
maxTime = -1;
|
||||
}
|
||||
else if (dl.state == gDownloadMgr.DOWNLOAD_PAUSED)
|
||||
numPaused++;
|
||||
}
|
||||
|
||||
// Get the remaining time string and last sec for time estimation
|
||||
let timeLeft;
|
||||
[timeLeft, this._lastTime] =
|
||||
this.DownloadUtils.getTimeLeft(maxTime, this._lastTime);
|
||||
|
||||
// Figure out how many downloads are currently downloading
|
||||
let numDls = numActive - numPaused;
|
||||
let status = this._activeStr;
|
||||
|
||||
// If all downloads are paused, show the paused message instead
|
||||
if (numDls == 0) {
|
||||
numDls = numPaused;
|
||||
status = this._pausedStr;
|
||||
}
|
||||
|
||||
// Get the correct plural form and insert the number of downloads and time
|
||||
// left message if necessary
|
||||
status = PluralForm.get(numDls, status);
|
||||
status = status.replace("#1", numDls);
|
||||
status = status.replace("#2", timeLeft);
|
||||
|
||||
// Update the panel and show it
|
||||
this._panel.label = status;
|
||||
this._panel.hidden = false;
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIDownloadProgressListener
|
||||
|
||||
/**
|
||||
* Update status for download progress changes
|
||||
*/
|
||||
onProgressChange: function() {
|
||||
this.updateStatus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update status for download state changes
|
||||
*/
|
||||
onDownloadStateChange: function() {
|
||||
this.updateStatus();
|
||||
},
|
||||
|
||||
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus, aDownload) {
|
||||
},
|
||||
|
||||
onSecurityChange: function(aWebProgress, aRequest, aState, aDownload) {
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsISupports
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadProgressListener]),
|
||||
};
|
||||
|
||||
function getNotificationBox(aWindow) {
|
||||
var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document);
|
||||
if (foundBrowser)
|
||||
|
|
|
@ -251,7 +251,6 @@ _BROWSER_FILES = \
|
|||
alltabslistener.html \
|
||||
zoom_test.html \
|
||||
dummy_page.html \
|
||||
browser_tabMatchesInAwesomebar.js \
|
||||
file_bug550565_popup.html \
|
||||
file_bug550565_favicon.ico \
|
||||
browser_aboutHome.js \
|
||||
|
@ -318,6 +317,7 @@ _BROWSER_FILES += \
|
|||
browser_private_browsing_window.js \
|
||||
browser_save_link-perwindowpb.js \
|
||||
browser_save_private_link_perwindowpb.js \
|
||||
browser_tabMatchesInAwesomebar_perwindowpb.js \
|
||||
$(NULL)
|
||||
else
|
||||
_BROWSER_FILES += \
|
||||
|
@ -325,6 +325,7 @@ _BROWSER_FILES += \
|
|||
browser_bug767836.js \
|
||||
browser_save_link.js \
|
||||
browser_save_private_link.js \
|
||||
browser_tabMatchesInAwesomebar.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -18,19 +18,19 @@ function test() {
|
|||
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aNormalWindow, aPrivateWindow, function() {
|
||||
runTest(aNormalWindow, aPrivateWindow, false, function() {
|
||||
aNormalWindow.close();
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aPrivateWindow, aNormalWindow, function() {
|
||||
runTest(aPrivateWindow, aNormalWindow, false, function() {
|
||||
aNormalWindow.close();
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({private: true}, function(aPrivateWindow) {
|
||||
runTest(aPrivateWindow, aPrivateWindow, function() {
|
||||
runTest(aPrivateWindow, aPrivateWindow, false, function() {
|
||||
aPrivateWindow.close();
|
||||
testOnWindow({}, function(aNormalWindow) {
|
||||
runTest(aNormalWindow, aNormalWindow, function() {
|
||||
runTest(aNormalWindow, aNormalWindow, true, function() {
|
||||
aNormalWindow.close();
|
||||
finish();
|
||||
});
|
||||
|
@ -44,7 +44,7 @@ function test() {
|
|||
});
|
||||
});
|
||||
|
||||
function runTest(aSourceWindow, aDestWindow, aCallback) {
|
||||
function runTest(aSourceWindow, aDestWindow, aExpectSuccess, aCallback) {
|
||||
// Open the base tab
|
||||
let baseTab = aSourceWindow.gBrowser.addTab(testURL);
|
||||
baseTab.linkedBrowser.addEventListener("load", function() {
|
||||
|
@ -91,21 +91,25 @@ function test() {
|
|||
function onTabClose(aEvent) {
|
||||
aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.removeEventListener("load", onLoad, false);
|
||||
clearTimeout(timeout);
|
||||
// Should only happen when we expect success
|
||||
ok(false, "Tab closed as expected");
|
||||
ok(aExpectSuccess, "Tab closed as expected");
|
||||
aCallback();
|
||||
}
|
||||
function onLoad(aEvent) {
|
||||
aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.removeEventListener("load", onLoad, false);
|
||||
clearTimeout(timeout);
|
||||
// Should only happen when we expect success
|
||||
ok(false, "Tab loaded as expected");
|
||||
ok(aExpectSuccess, "Tab loaded as expected");
|
||||
aCallback();
|
||||
}
|
||||
|
||||
aDestWindow.gBrowser.tabContainer.addEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.addEventListener("load", onLoad, false);
|
||||
setTimeout(function() {
|
||||
let timeout = setTimeout(function() {
|
||||
aDestWindow.gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, false);
|
||||
aDestWindow.gBrowser.removeEventListener("load", onLoad, false);
|
||||
aCallback();
|
||||
}, 500);
|
||||
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim:set ts=2 sw=2 sts=2 et:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const TEST_URL_BASES = [
|
||||
"http://example.org/browser/browser/base/content/test/dummy_page.html#tabmatch",
|
||||
"http://example.org/browser/browser/base/content/test/moz.png#tabmatch"
|
||||
];
|
||||
|
||||
var gController = Cc["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Ci.nsIAutoCompleteController);
|
||||
|
||||
var gTabWaitCount = 0;
|
||||
var gTabCounter = 0;
|
||||
|
||||
var gTestSteps = [
|
||||
function() {
|
||||
info("Running step 1");
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let tab = gBrowser.addTab();
|
||||
loadTab(tab, TEST_URL_BASES[0] + (++gTabCounter));
|
||||
}
|
||||
},
|
||||
function() {
|
||||
info("Running step 2");
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
for (let i = 1; i < gBrowser.tabs.length; i++)
|
||||
loadTab(gBrowser.tabs[i], TEST_URL_BASES[1] + (++gTabCounter));
|
||||
},
|
||||
function() {
|
||||
info("Running step 3");
|
||||
for (let i = 1; i < gBrowser.tabs.length; i++)
|
||||
loadTab(gBrowser.tabs[i], TEST_URL_BASES[0] + gTabCounter);
|
||||
},
|
||||
function() {
|
||||
info("Running step 4 - ensure we don't register subframes as open pages");
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
// Start the sub-document load.
|
||||
executeSoon(function () {
|
||||
tab.linkedBrowser.addEventListener("load", function (e) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}, true);
|
||||
tab.linkedBrowser.contentDocument.querySelector("iframe").src = "http://test2.example.org/";
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI('data:text/html,<body><iframe src=""></iframe></body>');
|
||||
},
|
||||
function() {
|
||||
info("Running step 5 - remove tab immediately");
|
||||
let tab = gBrowser.addTab("about:logo");
|
||||
gBrowser.removeTab(tab);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
},
|
||||
function() {
|
||||
info("Running step 6 - check swapBrowsersAndCloseOther preserves registered switch-to-tab result");
|
||||
let tabToKeep = gBrowser.addTab();
|
||||
let tab = gBrowser.addTab();
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
gBrowser.swapBrowsersAndCloseOther(tabToKeep, tab);
|
||||
ensure_opentabs_match_db(function () {
|
||||
gBrowser.removeTab(tabToKeep);
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI("about:mozilla");
|
||||
},
|
||||
function() {
|
||||
info("Running step 7 - close all tabs");
|
||||
|
||||
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
|
||||
|
||||
gBrowser.addTab("about:blank", {skipAnimation: true});
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
info("Removing tab: " + gBrowser.tabs[0].linkedBrowser.currentURI.spec);
|
||||
gBrowser.selectTabAtIndex(0);
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
nextStep();
|
||||
}
|
||||
|
||||
function loadTab(tab, url) {
|
||||
// Because adding visits is async, we will not be notified immediately.
|
||||
let visited = false;
|
||||
let loaded = false;
|
||||
|
||||
function maybeCheckResults() {
|
||||
if (visited && loaded && --gTabWaitCount == 0) {
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
}
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
loaded = true;
|
||||
maybeCheckResults();
|
||||
}, true);
|
||||
|
||||
if (!visited) {
|
||||
Services.obs.addObserver(
|
||||
function (aSubject, aTopic, aData) {
|
||||
if (url != aSubject.QueryInterface(Ci.nsIURI).spec)
|
||||
return;
|
||||
Services.obs.removeObserver(arguments.callee, aTopic);
|
||||
visited = true;
|
||||
maybeCheckResults();
|
||||
},
|
||||
"uri-visit-saved",
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
gTabWaitCount++;
|
||||
info("Loading page: " + url);
|
||||
tab.linkedBrowser.loadURI(url);
|
||||
}
|
||||
|
||||
function waitForRestoredTab(tab) {
|
||||
gTabWaitCount++;
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function () {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
if (--gTabWaitCount == 0) {
|
||||
ensure_opentabs_match_db(nextStep);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
function nextStep() {
|
||||
if (gTestSteps.length == 0) {
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.selectTabAtIndex(1);
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
||||
waitForClearHistory(finish);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var stepFunc = gTestSteps.shift();
|
||||
stepFunc();
|
||||
}
|
||||
|
||||
function ensure_opentabs_match_db(aCallback) {
|
||||
var tabs = {};
|
||||
|
||||
var winEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (winEnum.hasMoreElements()) {
|
||||
let browserWin = winEnum.getNext();
|
||||
// skip closed-but-not-destroyed windows
|
||||
if (browserWin.closed)
|
||||
continue;
|
||||
|
||||
for (let i = 0; i < browserWin.gBrowser.tabContainer.childElementCount; i++) {
|
||||
let browser = browserWin.gBrowser.getBrowserAtIndex(i);
|
||||
let url = browser.currentURI.spec;
|
||||
if (browserWin.isBlankPageURL(url))
|
||||
continue;
|
||||
if (!(url in tabs))
|
||||
tabs[url] = 1;
|
||||
else
|
||||
tabs[url]++;
|
||||
}
|
||||
}
|
||||
|
||||
checkAutocompleteResults(tabs, aCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
function waitForClearHistory(aCallback) {
|
||||
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
|
||||
aCallback();
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
|
||||
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
||||
function checkAutocompleteResults(aExpected, aCallback)
|
||||
{
|
||||
gController.input = {
|
||||
timeout: 10,
|
||||
textValue: "",
|
||||
searches: ["history"],
|
||||
searchParam: "enable-actions",
|
||||
popupOpen: false,
|
||||
minResultsForPopup: 0,
|
||||
invalidate: function() {},
|
||||
disableAutoComplete: false,
|
||||
completeDefaultIndex: false,
|
||||
get popup() { return this; },
|
||||
onSearchBegin: function() {},
|
||||
onSearchComplete: function ()
|
||||
{
|
||||
info("Found " + gController.matchCount + " matches.");
|
||||
// Check to see the expected uris and titles match up (in any order)
|
||||
for (let i = 0; i < gController.matchCount; i++) {
|
||||
let uri = gController.getValueAt(i).replace(/^moz-action:[^,]+,/i, "");
|
||||
|
||||
info("Search for '" + uri + "' in open tabs.");
|
||||
ok(uri in aExpected, "Registered open page found in autocomplete.");
|
||||
// Remove the found entry from expected results.
|
||||
delete aExpected[uri];
|
||||
}
|
||||
|
||||
// Make sure there is no reported open page that is not open.
|
||||
for (let entry in aExpected) {
|
||||
ok(false, "'" + entry + "' not found in autocomplete.");
|
||||
}
|
||||
|
||||
executeSoon(aCallback);
|
||||
},
|
||||
setSelectedIndex: function() {},
|
||||
get searchCount() { return this.searches.length; },
|
||||
getSearchAt: function(aIndex) this.searches[aIndex],
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIAutoCompleteInput,
|
||||
Ci.nsIAutoCompletePopup,
|
||||
])
|
||||
};
|
||||
|
||||
info("Searching open pages.");
|
||||
gController.startSearch(Services.prefs.getCharPref("browser.urlbar.restrict.openpage"));
|
||||
}
|
|
@ -13,10 +13,18 @@
|
|||
%globalDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
#ifdef XP_MACOSX
|
||||
<!ENTITY basePBMenu.label "&fileMenu.label;">
|
||||
#else
|
||||
<!ENTITY basePBMenu.label "<span class='appMenuButton'>&brandShortName;</span><span class='fileMenu'>&fileMenu.label;</span>">
|
||||
#endif
|
||||
#else
|
||||
#ifdef XP_MACOSX
|
||||
<!ENTITY basePBMenu.label "&toolsMenu.label;">
|
||||
#else
|
||||
<!ENTITY basePBMenu.label "<span class='appMenuButton'>&brandShortName;</span><span class='toolsMenu'>&toolsMenu.label;</span>">
|
||||
#endif
|
||||
#endif
|
||||
<!ENTITY % privatebrowsingpageDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
|
||||
%privatebrowsingpageDTD;
|
||||
|
@ -31,9 +39,15 @@
|
|||
body.private .showNormal {
|
||||
display: none;
|
||||
}
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
body.appMenuButtonVisible .fileMenu {
|
||||
display: none;
|
||||
}
|
||||
#else
|
||||
body.appMenuButtonVisible .toolsMenu {
|
||||
display: none;
|
||||
}
|
||||
#endif
|
||||
body.appMenuButtonInvisible .appMenuButton {
|
||||
display: none;
|
||||
}
|
||||
|
@ -94,9 +108,15 @@
|
|||
"appMenuButtonInvisible");
|
||||
}, false);
|
||||
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
function openPrivateWindow() {
|
||||
mainWindow.OpenBrowserWindow({private: true});
|
||||
}
|
||||
#else
|
||||
function togglePrivateBrowsing() {
|
||||
mainWindow.gPrivateBrowsingUI.toggleMode();
|
||||
}
|
||||
#endif
|
||||
]]></script>
|
||||
</head>
|
||||
|
||||
|
@ -117,27 +137,48 @@
|
|||
|
||||
<!-- Short Description -->
|
||||
<div id="errorShortDesc">
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
<p id="errorShortDescText" class="showPrivate">&privatebrowsingpage.perwindow.issueDesc;</p>
|
||||
<p id="errorShortDescTextNormal" class="showNormal">&privatebrowsingpage.perwindow.issueDesc.normal;</p>
|
||||
#else
|
||||
<p id="errorShortDescText" class="showPrivate">&privatebrowsingpage.issueDesc;</p>
|
||||
<p id="errorShortDescTextNormal" class="showNormal">&privatebrowsingpage.issueDesc.normal;</p>
|
||||
#endif
|
||||
</div>
|
||||
|
||||
<!-- Long Description -->
|
||||
<div id="errorLongDesc">
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
<p id="errorLongDescText">&privatebrowsingpage.perwindow.description;</p>
|
||||
#else
|
||||
<p id="errorLongDescText">&privatebrowsingpage.description;</p>
|
||||
#endif
|
||||
</div>
|
||||
|
||||
<!-- Start Private Browsing -->
|
||||
<div id="startPrivateBrowsingDesc" class="showNormal">
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
<button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="startPrivateBrowsing" label="&privatebrowsingpage.openPrivateWindow.label;"
|
||||
accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;"
|
||||
oncommand="openPrivateWindow();"/>
|
||||
#else
|
||||
<button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
id="startPrivateBrowsing" label="&privatebrowsingpage.startPrivateBrowsing.label;"
|
||||
accesskey="&privatebrowsingpage.startPrivateBrowsing.accesskey;"
|
||||
oncommand="togglePrivateBrowsing();"/>
|
||||
#endif
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div id="footerDesc">
|
||||
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
<p id="footerText" class="showPrivate">&privatebrowsingpage.howToStop3;</p>
|
||||
<p id="footerTextNormal" class="showNormal">&privatebrowsingpage.howToStart3;</p>
|
||||
#else
|
||||
<p id="footerText" class="showPrivate">&privatebrowsingpage.howToStop2;</p>
|
||||
<p id="footerTextNormal" class="showNormal">&privatebrowsingpage.howToStart2;</p>
|
||||
#endif
|
||||
</div>
|
||||
|
||||
<!-- More Info -->
|
||||
|
|
|
@ -24,10 +24,8 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_privatebrowsing_searchbar.js \
|
||||
browser_privatebrowsing_sslsite_transition.js \
|
||||
$(filter disabled-since-it-no-longer-makes-sense, browser_privatebrowsing_transition.js) \
|
||||
$(filter disabled--bug-564934, browser_privatebrowsing_downloadmonitor.js) \
|
||||
browser_privatebrowsing_urlbarundo.js \
|
||||
browser_privatebrowsing_viewsource.js \
|
||||
staller.sjs \
|
||||
$(NULL)
|
||||
|
||||
# Turn off private browsing tests that perma-timeout on Linux.
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This test makes sure that the download monitor status bar panel is correctly
|
||||
// cleared when switching the private browsing mode on or off.
|
||||
|
||||
function test() {
|
||||
// initialization
|
||||
let pb = Cc["@mozilla.org/privatebrowsing;1"].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
let dm = Cc["@mozilla.org/download-manager;1"].
|
||||
getService(Ci.nsIDownloadManager);
|
||||
if (!gDownloadMgr)
|
||||
gDownloadMgr = dm;
|
||||
let panel = document.getElementById("download-monitor");
|
||||
waitForExplicitFinish();
|
||||
|
||||
let acceptDialog = 0;
|
||||
let confirmCalls = 0;
|
||||
function promptObserver(aSubject, aTopic, aData) {
|
||||
let dialogWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
confirmCalls++;
|
||||
if (acceptDialog-- > 0)
|
||||
dialogWin.document.documentElement.getButton("accept").click();
|
||||
}
|
||||
|
||||
Services.obs.addObserver(promptObserver, "common-dialog-loaded", false);
|
||||
|
||||
// Add a new download
|
||||
let [file, persist] = addDownload(dm, {
|
||||
isPrivate: PrivateBrowsingUtils.isWindowPrivate(window),
|
||||
resultFileName: "pbtest-1",
|
||||
downloadName: "PB Test 1"
|
||||
});
|
||||
|
||||
// Make sure that the download is being displayed in the monitor panel
|
||||
if (!DownloadMonitorPanel.inited())
|
||||
DownloadMonitorPanel.init();
|
||||
else
|
||||
DownloadMonitorPanel.updateStatus();
|
||||
ok(!panel.hidden, "The download panel should be successfully added initially");
|
||||
|
||||
// Enter the private browsing mode
|
||||
acceptDialog = 1;
|
||||
pb.privateBrowsingEnabled = true;
|
||||
is(confirmCalls, 1, "One prompt was accepted");
|
||||
ok(pb.privateBrowsingEnabled, "The private browsing transition was successful");
|
||||
|
||||
executeSoon(function () {
|
||||
ok(panel.hidden, "The download panel should be hidden when entering the private browsing mode");
|
||||
|
||||
// Add a new download
|
||||
let [file2, persist2] = addDownload(dm, {
|
||||
isPrivate: PrivateBrowsingUtils.isWindowPrivate(window),
|
||||
resultFileName: "pbtest-2",
|
||||
downloadName: "PB Test 2"
|
||||
});
|
||||
|
||||
// Update the panel
|
||||
DownloadMonitorPanel.updateStatus();
|
||||
|
||||
// Make sure that the panel is visible
|
||||
ok(!panel.hidden, "The download panel should show up when a new download is added");
|
||||
|
||||
// Exit the private browsing mode
|
||||
acceptDialog = 1;
|
||||
pb.privateBrowsingEnabled = false;
|
||||
is(confirmCalls, 2, "One prompt was accepted");
|
||||
ok(!pb.privateBrowsingEnabled, "The private browsing transition was successful");
|
||||
|
||||
executeSoon(function () {
|
||||
ok(panel.hidden, "The download panel should be hidden when leaving the private browsing mode");
|
||||
|
||||
// cleanup
|
||||
let dls = dm.activeDownloads;
|
||||
while (dls.hasMoreElements()) {
|
||||
let dl = dls.getNext().QueryInterface(Ci.nsIDownload);
|
||||
dm.removeDownload(dl.id);
|
||||
let file = dl.targetFile;
|
||||
if (file.exists())
|
||||
file.remove(false);
|
||||
}
|
||||
if (file.exists())
|
||||
file.remove(false);
|
||||
|
||||
Services.obs.removeObserver(promptObserver, "common-dialog-loaded", false);
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a download to the DM, and starts it.
|
||||
* (Copied from toolkit/componentns/downloads/test/unit/head_download_manager.js)
|
||||
* @param aParams (optional): an optional object which contains the function
|
||||
* parameters:
|
||||
* resultFileName: leaf node for the target file
|
||||
* targetFile: nsIFile for the target (overrides resultFileName)
|
||||
* sourceURI: the download source URI
|
||||
* downloadName: the display name of the download
|
||||
* runBeforeStart: a function to run before starting the download
|
||||
* isPrivate: whether the download is private
|
||||
*/
|
||||
function addDownload(dm, aParams)
|
||||
{
|
||||
if (!aParams)
|
||||
aParams = {};
|
||||
if (!("resultFileName" in aParams))
|
||||
aParams.resultFileName = "download.result";
|
||||
if (!("targetFile" in aParams)) {
|
||||
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
aParams.targetFile = dirSvc.get("ProfD", Ci.nsIFile);
|
||||
aParams.targetFile.append(aParams.resultFileName);
|
||||
}
|
||||
if (!("sourceURI" in aParams))
|
||||
aParams.sourceURI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/global/staller.sjs";
|
||||
if (!("downloadName" in aParams))
|
||||
aParams.downloadName = null;
|
||||
if (!("runBeforeStart" in aParams))
|
||||
aParams.runBeforeStart = function () {};
|
||||
|
||||
const nsIWBP = Ci.nsIWebBrowserPersist;
|
||||
let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
|
||||
.createInstance(Ci.nsIWebBrowserPersist);
|
||||
persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
|
||||
nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
|
||||
nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
|
||||
let dl = dm.addDownload(Ci.nsIDownloadManager.DOWNLOAD_TYPE_DOWNLOAD,
|
||||
createURI(aParams.sourceURI),
|
||||
createURI(aParams.targetFile), aParams.downloadName, null,
|
||||
Math.round(Date.now() * 1000), null, persist, aParams.isPrivate);
|
||||
|
||||
// This will throw if it isn't found, and that would mean test failure, so no
|
||||
// try catch block
|
||||
let test = dm.getDownload(dl.id);
|
||||
|
||||
aParams.runBeforeStart.call(undefined, dl);
|
||||
|
||||
persist.progressListener = dl.QueryInterface(Ci.nsIWebProgressListener);
|
||||
persist.savePrivacyAwareURI(dl.source, null, null, null, null, dl.targetFile,
|
||||
aParams.isPrivate);
|
||||
|
||||
return [dl.targetFile, persist];
|
||||
}
|
||||
|
||||
function createURI(aObj) {
|
||||
let ios = Services.io;
|
||||
return (aObj instanceof Ci.nsIFile) ? ios.newFileURI(aObj) :
|
||||
ios.newURI(aObj, null, null);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This provides the tests with a download URL which never finishes.
|
||||
|
||||
var timer;
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine(request.httpVersion, 200, "OK");
|
||||
response.processAsync();
|
||||
|
||||
const nsITimer = Components.interfaces.nsITimer;
|
||||
|
||||
function stall() {
|
||||
timer = null;
|
||||
// This write will throw if the connection has been closed by the browser.
|
||||
response.write("stalling...\n");
|
||||
timer = Components.classes["@mozilla.org/timer;1"]
|
||||
.createInstance(nsITimer);
|
||||
timer.initWithCallback(stall, 500, nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "text/plain", false);
|
||||
response.setHeader("Accept-Ranges", "none", false);
|
||||
stall();
|
||||
}
|
|
@ -69,7 +69,6 @@ _BROWSER_FILES = \
|
|||
browser_tabview_bug622835.js \
|
||||
browser_tabview_bug623768.js \
|
||||
browser_tabview_bug624692.js \
|
||||
browser_tabview_bug624727.js \
|
||||
browser_tabview_bug624847.js \
|
||||
browser_tabview_bug624931.js \
|
||||
browser_tabview_bug624953.js \
|
||||
|
@ -107,7 +106,6 @@ _BROWSER_FILES = \
|
|||
browser_tabview_bug649006.js \
|
||||
browser_tabview_bug649307.js \
|
||||
browser_tabview_bug649319.js \
|
||||
browser_tabview_bug650280.js \
|
||||
browser_tabview_bug650573.js \
|
||||
browser_tabview_bug651311.js \
|
||||
browser_tabview_bug654295.js \
|
||||
|
@ -150,7 +148,6 @@ _BROWSER_FILES = \
|
|||
browser_tabview_group.js \
|
||||
browser_tabview_launch.js \
|
||||
browser_tabview_multiwindow_search.js \
|
||||
browser_tabview_privatebrowsing.js \
|
||||
browser_tabview_rtl.js \
|
||||
browser_tabview_search.js \
|
||||
browser_tabview_snapping.js \
|
||||
|
@ -169,10 +166,15 @@ _BROWSER_FILES = \
|
|||
ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
_BROWSER_FILES += \
|
||||
browser_tabview_bug624265_perwindowpb.js \
|
||||
browser_tabview_bug624727_perwindowpb.js \
|
||||
browser_tabview_bug650280_perwindowpb.js \
|
||||
$(NULL)
|
||||
else
|
||||
_BROWSER_FILES += \
|
||||
browser_tabview_bug624265.js \
|
||||
browser_tabview_bug624727.js \
|
||||
browser_tabview_bug650280.js \
|
||||
browser_tabview_privatebrowsing.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let createGroupItem = function (aWindow) {
|
||||
let cw = aWindow.TabView.getContentWindow();
|
||||
let bounds = new cw.Rect(20, 20, 400, 200);
|
||||
let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
|
||||
cw.UI.setActive(groupItem);
|
||||
|
||||
let groupItemId = groupItem.id;
|
||||
registerCleanupFunction(function() {
|
||||
let groupItem = cw.GroupItems.groupItem(groupItemId);
|
||||
if (groupItem)
|
||||
groupItem.close();
|
||||
});
|
||||
|
||||
for (let i=0; i<3; i++)
|
||||
aWindow.gBrowser.addTab('about:blank');
|
||||
}
|
||||
|
||||
let assertTabViewIsHidden = function (aWindow, prefix) {
|
||||
ok(!aWindow.TabView.isVisible(), prefix + ': tabview is hidden');
|
||||
}
|
||||
|
||||
let assertNumberOfTabs = function (aWindow, prefix, num) {
|
||||
is(aWindow.gBrowser.tabs.length, num, prefix + ': there are ' + num + ' tabs');
|
||||
}
|
||||
|
||||
let assertNumberOfPinnedTabs = function (aWindow, prefix, num) {
|
||||
is(aWindow.gBrowser._numPinnedTabs, num, prefix + ': there are ' + num + ' pinned tabs');
|
||||
}
|
||||
|
||||
let assertNumberOfGroups = function (aCW, prefix, num) {
|
||||
is(aCW.GroupItems.groupItems.length, num, prefix + ': there are ' + num + ' groups');
|
||||
}
|
||||
|
||||
let assertOneTabInGroup = function (prefix, groupItem) {
|
||||
is(groupItem.getChildren().length, 1, prefix + ': group contains one tab');
|
||||
}
|
||||
|
||||
let assertValidPrerequisites = function (aWindow, prefix) {
|
||||
assertNumberOfTabs(aWindow, prefix, 1);
|
||||
assertNumberOfPinnedTabs(aWindow, prefix, 0);
|
||||
assertTabViewIsHidden(aWindow, prefix);
|
||||
}
|
||||
|
||||
let assertValidSetup = function (aWindow, prefix) {
|
||||
let cw = aWindow.TabView.getContentWindow();
|
||||
assertNumberOfGroups(cw, prefix, 2);
|
||||
assertNumberOfTabs(aWindow, prefix, 4);
|
||||
assertNumberOfPinnedTabs(aWindow, prefix, 2);
|
||||
|
||||
let [group1, group2] = cw.GroupItems.groupItems;
|
||||
assertOneTabInGroup(prefix, group1);
|
||||
assertOneTabInGroup(prefix, group2);
|
||||
}
|
||||
|
||||
let testStateAfterEnteringPB = function (aWindow, aCallback) {
|
||||
let prefix = 'window is private';
|
||||
ok(PrivateBrowsingUtils.isWindowPrivate(aWindow), prefix);
|
||||
|
||||
assertTabViewIsHidden(aWindow, prefix);
|
||||
|
||||
showTabView(function () {
|
||||
let cw = aWindow.TabView.getContentWindow();
|
||||
|
||||
assertNumberOfGroups(cw, prefix, 1);
|
||||
assertNumberOfTabs(aWindow, prefix, 1);
|
||||
assertOneTabInGroup(prefix, cw.GroupItems.groupItems[0]);
|
||||
aCallback();
|
||||
}, aWindow);
|
||||
}
|
||||
|
||||
let testStateAfterLeavingPB = function (aWindow) {
|
||||
let prefix = 'window is not private';
|
||||
ok(!PrivateBrowsingUtils.isWindowPrivate(aWindow), prefix);
|
||||
|
||||
assertTabViewIsHidden(aWindow, prefix);
|
||||
|
||||
showTabView(function () {
|
||||
assertValidSetup(aWindow, prefix);
|
||||
finishTest(aWindow);
|
||||
}, aWindow);
|
||||
}
|
||||
|
||||
let finishTest = function (aWindow) {
|
||||
let cw = aWindow.TabView.getContentWindow();
|
||||
|
||||
// Remove pinned tabs
|
||||
aWindow.gBrowser.removeTab(aWindow.gBrowser.tabs[0]);
|
||||
aWindow.gBrowser.removeTab(aWindow.gBrowser.tabs[0]);
|
||||
|
||||
cw.GroupItems.groupItems[1].closeAll();
|
||||
|
||||
hideTabView(function () {
|
||||
assertValidPrerequisites(aWindow, 'exit');
|
||||
assertNumberOfGroups(cw, 'exit', 1);
|
||||
aWindow.close();
|
||||
finish();
|
||||
}, aWindow);
|
||||
}
|
||||
|
||||
let testOnWindow = function(aIsPrivate, aCallback) {
|
||||
let win = OpenBrowserWindow({private: aIsPrivate});
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function() { aCallback(win) });
|
||||
}, false);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
testOnWindow(false, function(publicWindow) {
|
||||
registerCleanupFunction(function () publicWindow.TabView.hide());
|
||||
assertValidPrerequisites(publicWindow, 'start');
|
||||
|
||||
showTabView(function () {
|
||||
let cw = publicWindow.TabView.getContentWindow();
|
||||
assertNumberOfGroups(cw, 'start', 1);
|
||||
createGroupItem(publicWindow);
|
||||
|
||||
afterAllTabsLoaded(function () {
|
||||
// Setup
|
||||
let groupItems = cw.GroupItems.groupItems;
|
||||
let [tabItem1, tabItem2, ] = groupItems[1].getChildren();
|
||||
publicWindow.gBrowser.pinTab(tabItem1.tab);
|
||||
publicWindow.gBrowser.pinTab(tabItem2.tab);
|
||||
|
||||
assertValidSetup(publicWindow, 'setup');
|
||||
hideTabView(function() {
|
||||
testOnWindow(true, function(privateWindow) {
|
||||
testStateAfterEnteringPB(privateWindow, function() {
|
||||
privateWindow.close();
|
||||
hideTabView(function() {
|
||||
testStateAfterLeavingPB(publicWindow);
|
||||
}, publicWindow);
|
||||
});
|
||||
});
|
||||
}, publicWindow);
|
||||
});
|
||||
}, publicWindow);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let enableSearch = function (aCW, aCallback) {
|
||||
if (aCW.Search.isEnabled()) {
|
||||
aCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
aCW.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
|
||||
aCW.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
|
||||
executeSoon(aCallback);
|
||||
}, false);
|
||||
|
||||
aCW.Search.ensureShown();
|
||||
};
|
||||
|
||||
let getSearchboxValue = function (aCW) {
|
||||
return aCW.iQ("#searchbox").val();
|
||||
};
|
||||
|
||||
let prepareSearchbox = function (aCW, aCallback) {
|
||||
ok(!aCW.Search.isEnabled(), "search is disabled");
|
||||
|
||||
executeSoon(function() {
|
||||
enableSearch(aCW, function() {
|
||||
aCW.iQ("#searchbox").val("moz");
|
||||
aCallback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
let searchAndSwitchPBMode = function (aWindow, aCallback) {
|
||||
showTabView(function() {
|
||||
let cw = aWindow.TabView.getContentWindow();
|
||||
|
||||
prepareSearchbox(cw, function() {
|
||||
testOnWindow(!PrivateBrowsingUtils.isWindowPrivate(aWindow), function(win) {
|
||||
showTabView(function() {
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
ok(!contentWindow.Search.isEnabled(), "search is disabled");
|
||||
is(getSearchboxValue(contentWindow), "", "search box is empty");
|
||||
aWindow.TabView.hide();
|
||||
win.close();
|
||||
hideTabView(function() {
|
||||
aWindow.close();
|
||||
aCallback();
|
||||
}, aWindow);
|
||||
}, win);
|
||||
});
|
||||
});
|
||||
}, aWindow);
|
||||
};
|
||||
|
||||
let testOnWindow = function(aIsPrivate, aCallback) {
|
||||
let win = OpenBrowserWindow({private: aIsPrivate});
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
executeSoon(function() { aCallback(win) });
|
||||
}, false);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
testOnWindow(false, function(win) {
|
||||
searchAndSwitchPBMode(win, function() {
|
||||
testOnWindow(true, function(win) {
|
||||
searchAndSwitchPBMode(win, function() {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r168596"
|
||||
"clang_version": "r169139"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 62525599,
|
||||
"digest": "50818d3288713821a520c3c4c5b01f0a782a5ac5b4c8f5d2a198af150323b93d07bf6b5f87d9ef4a9b49308ce788112907a211b02d7d5123338ad6a0265100b8",
|
||||
"size": 62513298,
|
||||
"digest": "1c9dfc75d4a06438da4d079282178274054e07d814ec6bc8e45c9e62589293df11858c74ce301c53b5bd758c56dc1c593a97cd5034b47ea753c518fd9af69ea4",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r168596"
|
||||
"clang_version": "r169139"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 62868457,
|
||||
"digest": "f5ebd0e6a3238f309ac554f266a58e558e08dd5959579c8b9dd78ce1d88162990d850bad3164dccfced5ce2cf5aa1448baaf94878ad96c1a5fa025e567bf0d61",
|
||||
"size": 62856551,
|
||||
"digest": "3542a25815f89555f2e2b4c67fbffa432c341d824395b452698d8d90ee0216e045531adcad14bf7071be1a41c016b4652cf955270b652bcdbd7b04a02cc3c9f9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r168596"
|
||||
"clang_version": "r169139"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 56147341,
|
||||
"digest": "4baed5cbe0189a509b6a328ee35ee488250677f8ea149e6d01af74c7a4a27c898a4112f78af57b33a4e788b2947813b65ab0922e06b67bd504878803dab44f5c",
|
||||
"size": 56158651,
|
||||
"digest": "38d718f20a8fa9218e22ade312e724e6c9cdd7c6650e023cfdc21b5505fe7aa3743ae41c0abd717a1bbccec4c4271be2fa82d0e2f96c91e693d70e33b4dc00d6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r168596"
|
||||
"clang_version": "r169139"
|
||||
},
|
||||
{
|
||||
"size": 47,
|
||||
|
@ -9,8 +9,8 @@
|
|||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 56147341,
|
||||
"digest": "4baed5cbe0189a509b6a328ee35ee488250677f8ea149e6d01af74c7a4a27c898a4112f78af57b33a4e788b2947813b65ab0922e06b67bd504878803dab44f5c",
|
||||
"size": 56158651,
|
||||
"digest": "38d718f20a8fa9218e22ade312e724e6c9cdd7c6650e023cfdc21b5505fe7aa3743ae41c0abd717a1bbccec4c4271be2fa82d0e2f96c91e693d70e33b4dc00d6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2"
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "CommandUtils",
|
|||
|
||||
// DO NOT put Require.jsm or gcli.jsm into lazy getters as this breaks the
|
||||
// requisition import a few lines down.
|
||||
Cu.import("resource://gre/modules/devtools/gcli.jsm");
|
||||
Cu.import("resource:///modules/devtools/gcli.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Require.jsm");
|
||||
|
||||
let Requisition = require('gcli/cli').Requisition;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
let tempScope = {};
|
||||
Components.utils.import("resource:///modules/devtools/Target.jsm", tempScope);
|
||||
let TargetFactory = tempScope.TargetFactory;
|
||||
Components.utils.import("resource:///modules/devtools/Console.jsm", tempScope);
|
||||
Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
|
||||
let console = tempScope.console;
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MarkupView",
|
||||
"resource://gre/modules/devtools/MarkupView.jsm");
|
||||
"resource:///modules/devtools/MarkupView.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Selection",
|
||||
"resource:///modules/devtools/Selection.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "HTMLBreadcrumbs",
|
||||
|
|
|
@ -370,17 +370,25 @@ StyleEditorChrome.prototype = {
|
|||
aEditor.removeActionListener(this);
|
||||
self.selectedStyleSheetIndex = aEditor.styleSheetIndex;
|
||||
aEditor.sourceEditor.setCaretPosition(line - 1, col - 1);
|
||||
|
||||
let newSheet = self._styleSheetToSelect.sheet;
|
||||
let newLine = self._styleSheetToSelect.line;
|
||||
let newCol = self._styleSheetToSelect.col;
|
||||
self._styleSheetToSelect = null;
|
||||
if (newSheet != sheet) {
|
||||
self._window.setTimeout(self.selectStyleSheet.bind(self, newSheet, newLine, newCol), 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// If a line or column was specified we move the caret appropriately.
|
||||
aEditor.sourceEditor.setCaretPosition(line - 1, col - 1);
|
||||
self._styleSheetToSelect = null;
|
||||
}
|
||||
}
|
||||
|
||||
this._view.activeSummary = summary;
|
||||
this.selectedStyleSheetIndex = aEditor.styleSheetIndex;
|
||||
this._styleSheetToSelect = null;
|
||||
}.bind(this);
|
||||
|
||||
if (!this.editors.length) {
|
||||
|
|
|
@ -150,6 +150,9 @@ function performLineCheck(aEditor, aLine, aCallback)
|
|||
return aEditor.sourceEditor;
|
||||
},
|
||||
successFn: checkForCorrectState,
|
||||
failureFn: finishTest,
|
||||
failureFn: function() {
|
||||
info("selectedStyleSheetIndex " + SEC.selectedStyleSheetIndex + " expected " + aEditor.styleSheetIndex);
|
||||
finishTest();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 0.6.141
|
||||
Current extension version is: 0.6.172
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ var PDFJS = {};
|
|||
'use strict';
|
||||
|
||||
PDFJS.build =
|
||||
'033545c';
|
||||
'3c7ef79';
|
||||
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
@ -517,6 +517,17 @@ var PDFDocument = (function PDFDocumentClosure() {
|
|||
if (find(stream, '%PDF-', 1024)) {
|
||||
// Found the header, trim off any garbage before it.
|
||||
stream.moveStart();
|
||||
// Reading file format version
|
||||
var MAX_VERSION_LENGTH = 12;
|
||||
var version = '', ch;
|
||||
while ((ch = stream.getChar()) > ' ') {
|
||||
if (version.length >= MAX_VERSION_LENGTH) {
|
||||
break;
|
||||
}
|
||||
version += ch;
|
||||
}
|
||||
// removing "%PDF-"-prefix
|
||||
this.pdfFormatVersion = version.substring(5);
|
||||
return;
|
||||
}
|
||||
// May not be a PDF file, continue anyway.
|
||||
|
@ -537,11 +548,12 @@ var PDFDocument = (function PDFDocumentClosure() {
|
|||
return shadow(this, 'numPages', num);
|
||||
},
|
||||
getDocumentInfo: function PDFDocument_getDocumentInfo() {
|
||||
var docInfo;
|
||||
var docInfo = {
|
||||
PDFFormatVersion: this.pdfFormatVersion
|
||||
};
|
||||
if (this.xref.trailer.has('Info')) {
|
||||
var infoDict = this.xref.trailer.get('Info');
|
||||
|
||||
docInfo = {};
|
||||
var validEntries = DocumentInfoValidators.entries;
|
||||
// Only fill the document info with valid entries from the spec.
|
||||
for (var key in validEntries) {
|
||||
|
@ -658,6 +670,8 @@ function assert(cond, msg) {
|
|||
// Combines two URLs. The baseUrl shall be absolute URL. If the url is an
|
||||
// absolute URL, it will be returned as is.
|
||||
function combineUrl(baseUrl, url) {
|
||||
if (!url)
|
||||
return baseUrl;
|
||||
if (url.indexOf(':') >= 0)
|
||||
return url;
|
||||
if (url.charAt(0) == '/') {
|
||||
|
@ -767,15 +781,17 @@ var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
|||
var Util = PDFJS.Util = (function UtilClosure() {
|
||||
function Util() {}
|
||||
|
||||
Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
|
||||
var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
|
||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||
Util.makeCssRgb = function Util_makeCssRgb(rgb) {
|
||||
return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
|
||||
};
|
||||
|
||||
Util.makeCssCmyk = function Util_makeCssCmyk(c, m, y, k) {
|
||||
c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
|
||||
var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
|
||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||
Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) {
|
||||
var cs = new DeviceCmykCS();
|
||||
Util.makeCssCmyk = function makeCssCmyk(cmyk) {
|
||||
var rgb = cs.getRgb(cmyk, 0);
|
||||
return Util.makeCssRgb(rgb);
|
||||
};
|
||||
return Util.makeCssCmyk(cmyk);
|
||||
};
|
||||
|
||||
// For 2d affine transforms
|
||||
|
@ -2899,8 +2915,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
},
|
||||
setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) {
|
||||
var cs = this.current.strokeColorSpace;
|
||||
var rgbColor = cs.getRgb(arguments);
|
||||
var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
|
||||
var rgbColor = cs.getRgb(arguments, 0);
|
||||
var color = Util.makeCssRgb(rgbColor);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
|
@ -2912,11 +2928,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
if (base) {
|
||||
var baseComps = base.numComps;
|
||||
|
||||
color = [];
|
||||
for (var i = 0; i < baseComps; ++i)
|
||||
color.push(args[i]);
|
||||
|
||||
color = base.getRgb(color);
|
||||
color = base.getRgb(args, 0);
|
||||
}
|
||||
var pattern = new TilingPattern(IR, color, this.ctx, this.objs);
|
||||
} else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
|
||||
|
@ -2937,8 +2949,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
},
|
||||
setFillColor: function CanvasGraphics_setFillColor(/*...*/) {
|
||||
var cs = this.current.fillColorSpace;
|
||||
var rgbColor = cs.getRgb(arguments);
|
||||
var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
|
||||
var rgbColor = cs.getRgb(arguments, 0);
|
||||
var color = Util.makeCssRgb(rgbColor);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
|
@ -2955,7 +2967,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
if (!(this.current.strokeColorSpace instanceof DeviceGrayCS))
|
||||
this.current.strokeColorSpace = new DeviceGrayCS();
|
||||
|
||||
var color = Util.makeCssRgb(gray, gray, gray);
|
||||
var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
|
||||
var color = Util.makeCssRgb(rgbColor);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
|
@ -2963,7 +2976,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
if (!(this.current.fillColorSpace instanceof DeviceGrayCS))
|
||||
this.current.fillColorSpace = new DeviceGrayCS();
|
||||
|
||||
var color = Util.makeCssRgb(gray, gray, gray);
|
||||
var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
|
||||
var color = Util.makeCssRgb(rgbColor);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
|
@ -2971,7 +2985,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
if (!(this.current.strokeColorSpace instanceof DeviceRgbCS))
|
||||
this.current.strokeColorSpace = new DeviceRgbCS();
|
||||
|
||||
var color = Util.makeCssRgb(r, g, b);
|
||||
var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
|
||||
var color = Util.makeCssRgb(rgbColor);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
|
@ -2979,7 +2994,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
if (!(this.current.fillColorSpace instanceof DeviceRgbCS))
|
||||
this.current.fillColorSpace = new DeviceRgbCS();
|
||||
|
||||
var color = Util.makeCssRgb(r, g, b);
|
||||
var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
|
||||
var color = Util.makeCssRgb(rgbColor);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
|
@ -2987,7 +3003,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
if (!(this.current.strokeColorSpace instanceof DeviceCmykCS))
|
||||
this.current.strokeColorSpace = new DeviceCmykCS();
|
||||
|
||||
var color = Util.makeCssCmyk(c, m, y, k);
|
||||
var color = Util.makeCssCmyk(arguments);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
|
@ -2995,7 +3011,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
if (!(this.current.fillColorSpace instanceof DeviceCmykCS))
|
||||
this.current.fillColorSpace = new DeviceCmykCS();
|
||||
|
||||
var color = Util.makeCssCmyk(c, m, y, k);
|
||||
var color = Util.makeCssCmyk(arguments);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
|
@ -3580,11 +3596,13 @@ var Catalog = (function CatalogClosure() {
|
|||
continue;
|
||||
}
|
||||
var names = obj.get('Names');
|
||||
if (names) {
|
||||
for (i = 0, n = names.length; i < n; i += 2) {
|
||||
dests[names[i]] = fetchDestination(xref.fetchIfRef(names[i + 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return shadow(this, 'destinations', dests);
|
||||
},
|
||||
getPage: function Catalog_getPage(n) {
|
||||
|
@ -12053,15 +12071,58 @@ var ColorSpace = (function ColorSpaceClosure() {
|
|||
}
|
||||
|
||||
ColorSpace.prototype = {
|
||||
// Input: array of size numComps representing color component values
|
||||
// Output: array of rgb values, each value ranging from [0.1]
|
||||
getRgb: function ColorSpace_getRgb(color) {
|
||||
error('Should not call ColorSpace.getRgb: ' + color);
|
||||
/**
|
||||
* Converts the color value to the RGB color. The color components are
|
||||
* located in the src array starting from the srcOffset. Returns the array
|
||||
* of the rgb components, each value ranging from [0,255].
|
||||
*/
|
||||
getRgb: function ColorSpace_getRgb(src, srcOffset) {
|
||||
error('Should not call ColorSpace.getRgb');
|
||||
},
|
||||
// Input: Uint8Array of component values, each value scaled to [0,255]
|
||||
// Output: Uint8Array of rgb values, each value scaled to [0,255]
|
||||
getRgbBuffer: function ColorSpace_getRgbBuffer(input) {
|
||||
error('Should not call ColorSpace.getRgbBuffer: ' + input);
|
||||
/**
|
||||
* Converts the color value to the RGB color, similar to the getRgb method.
|
||||
* The result placed into the dest array starting from the destOffset.
|
||||
*/
|
||||
getRgbItem: function ColorSpace_getRgb(src, srcOffset, dest, destOffset) {
|
||||
error('Should not call ColorSpace.getRgbItem');
|
||||
},
|
||||
/**
|
||||
* Converts the specified number of the color values to the RGB colors.
|
||||
* The colors are located in the src array starting from the srcOffset.
|
||||
* The result is placed into the dest array starting from the destOffset.
|
||||
* The src array items shall be in [0,2^bits) range, the dest array items
|
||||
* will be in [0,255] range.
|
||||
*/
|
||||
getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
|
||||
dest, destOffset, bits) {
|
||||
error('Should not call ColorSpace.getRgbBuffer');
|
||||
},
|
||||
/**
|
||||
* Determines amount of the bytes is required to store the reslut of the
|
||||
* conversion that done by the getRgbBuffer method.
|
||||
*/
|
||||
getOutputLength: function ColorSpace_getOutputLength(inputLength) {
|
||||
error('Should not call ColorSpace.getOutputLength');
|
||||
},
|
||||
/**
|
||||
* Returns true if source data will be equal the result/output data.
|
||||
*/
|
||||
isPassthrough: function ColorSpace_isPassthrough(bits) {
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* Creates the output buffer and converts the specified number of the color
|
||||
* values to the RGB colors, similar to the getRgbBuffer.
|
||||
*/
|
||||
createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset,
|
||||
count, bits) {
|
||||
if (this.isPassthrough(bits)) {
|
||||
return src.subarray(srcOffset);
|
||||
}
|
||||
var destLength = this.getOutputLength(count * this.numComps);
|
||||
var dest = new Uint8Array(destLength);
|
||||
this.getRgbBuffer(src, srcOffset, count, dest, 0, bits);
|
||||
return dest;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12245,39 +12306,66 @@ var AlternateCS = (function AlternateCSClosure() {
|
|||
function AlternateCS(numComps, base, tintFn) {
|
||||
this.name = 'Alternate';
|
||||
this.numComps = numComps;
|
||||
this.defaultColor = [];
|
||||
for (var i = 0; i < numComps; ++i)
|
||||
this.defaultColor.push(1);
|
||||
this.defaultColor = new Float32Array(numComps);
|
||||
for (var i = 0; i < numComps; ++i) {
|
||||
this.defaultColor[i] = 1;
|
||||
}
|
||||
this.base = base;
|
||||
this.tintFn = tintFn;
|
||||
}
|
||||
|
||||
AlternateCS.prototype = {
|
||||
getRgb: function AlternateCS_getRgb(color) {
|
||||
var tinted = this.tintFn(color);
|
||||
return this.base.getRgb(tinted);
|
||||
getRgb: function AlternateCS_getRgb(src, srcOffset) {
|
||||
var rgb = new Uint8Array(3);
|
||||
this.getRgbItem(src, srcOffset, rgb, 0);
|
||||
return rgb;
|
||||
},
|
||||
getRgbBuffer: function AlternateCS_getRgbBuffer(input, bits) {
|
||||
getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
|
||||
dest, destOffset) {
|
||||
var baseNumComps = this.base.numComps;
|
||||
var input = 'subarray' in src ?
|
||||
src.subarray(srcOffset, srcOffset + this.numComps) :
|
||||
Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
|
||||
var tinted = this.tintFn(input);
|
||||
this.base.getRgbItem(tinted, 0, dest, destOffset);
|
||||
},
|
||||
getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count,
|
||||
dest, destOffset, bits) {
|
||||
var tintFn = this.tintFn;
|
||||
var base = this.base;
|
||||
var scale = 1 / ((1 << bits) - 1);
|
||||
var length = input.length;
|
||||
var pos = 0;
|
||||
var baseNumComps = base.numComps;
|
||||
var baseBuf = new Uint8Array(baseNumComps * length);
|
||||
var isGetRgbBufferSupported = 'getRgbBuffer' in base;
|
||||
var isPassthrough = base.isPassthrough(8) || !isGetRgbBufferSupported;
|
||||
var pos = isPassthrough ? destOffset : 0;
|
||||
var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
|
||||
var numComps = this.numComps;
|
||||
var scaled = [];
|
||||
|
||||
for (var i = 0; i < length; i += numComps) {
|
||||
for (var z = 0; z < numComps; ++z)
|
||||
scaled[z] = input[i + z] * scale;
|
||||
|
||||
var tinted = tintFn(scaled);
|
||||
for (var j = 0; j < baseNumComps; ++j)
|
||||
baseBuf[pos++] = 255 * tinted[j];
|
||||
var scaled = new Float32Array(numComps);
|
||||
for (var i = 0; i < count; i++) {
|
||||
for (var j = 0; j < numComps; j++) {
|
||||
scaled[j] = src[srcOffset++] * scale;
|
||||
}
|
||||
var tinted = tintFn(scaled);
|
||||
if (isGetRgbBufferSupported) {
|
||||
for (var j = 0; j < baseNumComps; j++) {
|
||||
baseBuf[pos++] = tinted[j] * 255;
|
||||
}
|
||||
} else {
|
||||
base.getRgbItem(tinted, 0, baseBuf, pos);
|
||||
pos += baseNumComps;
|
||||
}
|
||||
}
|
||||
if (!isPassthrough) {
|
||||
base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8);
|
||||
}
|
||||
return base.getRgbBuffer(baseBuf, 8);
|
||||
},
|
||||
getOutputLength: function AlternateCS_getOutputLength(inputLength) {
|
||||
return this.base.getOutputLength(inputLength *
|
||||
this.base.numComps / this.numComps);
|
||||
},
|
||||
isPassthrough: ColorSpace.prototype.isPassthrough,
|
||||
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
|
||||
isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
|
||||
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
|
||||
}
|
||||
|
@ -12300,7 +12388,7 @@ var IndexedCS = (function IndexedCSClosure() {
|
|||
function IndexedCS(base, highVal, lookup) {
|
||||
this.name = 'Indexed';
|
||||
this.numComps = 1;
|
||||
this.defaultColor = [0];
|
||||
this.defaultColor = new Uint8Array([0]);
|
||||
this.base = base;
|
||||
this.highVal = highVal;
|
||||
|
||||
|
@ -12325,33 +12413,35 @@ var IndexedCS = (function IndexedCSClosure() {
|
|||
}
|
||||
|
||||
IndexedCS.prototype = {
|
||||
getRgb: function IndexedCS_getRgb(color) {
|
||||
getRgb: function IndexedCS_getRgb(src, srcOffset) {
|
||||
var numComps = this.base.numComps;
|
||||
var start = color[0] * numComps;
|
||||
var c = [];
|
||||
|
||||
for (var i = start, ii = start + numComps; i < ii; ++i)
|
||||
c.push(this.lookup[i]);
|
||||
|
||||
return this.base.getRgb(c);
|
||||
var start = src[srcOffset] * numComps;
|
||||
return this.base.getRgb(this.lookup, start);
|
||||
},
|
||||
getRgbBuffer: function IndexedCS_getRgbBuffer(input) {
|
||||
getRgbItem: function IndexedCS_getRgbItem(src, srcOffset,
|
||||
dest, destOffset) {
|
||||
var numComps = this.base.numComps;
|
||||
var start = src[srcOffset] * numComps;
|
||||
this.base.getRgbItem(this.lookup, start, dest, destOffset);
|
||||
},
|
||||
getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count,
|
||||
dest, destOffset) {
|
||||
var base = this.base;
|
||||
var numComps = base.numComps;
|
||||
var outputDelta = base.getOutputLength(numComps);
|
||||
var lookup = this.lookup;
|
||||
var length = input.length;
|
||||
var baseBuf = new Uint8Array(length * numComps);
|
||||
var baseBufPos = 0;
|
||||
|
||||
for (var i = 0; i < length; ++i) {
|
||||
var lookupPos = input[i] * numComps;
|
||||
for (var j = 0; j < numComps; ++j) {
|
||||
baseBuf[baseBufPos++] = lookup[lookupPos + j];
|
||||
for (var i = 0; i < count; ++i) {
|
||||
var lookupPos = src[srcOffset++] * numComps;
|
||||
base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8);
|
||||
destOffset += outputDelta;
|
||||
}
|
||||
}
|
||||
|
||||
return base.getRgbBuffer(baseBuf, 8);
|
||||
},
|
||||
getOutputLength: function IndexedCS_getOutputLength(inputLength) {
|
||||
return this.base.getOutputLength(inputLength * this.base.numComps);
|
||||
},
|
||||
isPassthrough: ColorSpace.prototype.isPassthrough,
|
||||
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
|
||||
isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
|
||||
// indexed color maps shouldn't be changed
|
||||
return true;
|
||||
|
@ -12364,26 +12454,37 @@ var DeviceGrayCS = (function DeviceGrayCSClosure() {
|
|||
function DeviceGrayCS() {
|
||||
this.name = 'DeviceGray';
|
||||
this.numComps = 1;
|
||||
this.defaultColor = [0];
|
||||
this.defaultColor = new Float32Array([0]);
|
||||
}
|
||||
|
||||
DeviceGrayCS.prototype = {
|
||||
getRgb: function DeviceGrayCS_getRgb(color) {
|
||||
var c = color[0];
|
||||
return [c, c, c];
|
||||
getRgb: function DeviceGrayCS_getRgb(src, srcOffset) {
|
||||
var rgb = new Uint8Array(3);
|
||||
this.getRgbItem(src, srcOffset, rgb, 0);
|
||||
return rgb;
|
||||
},
|
||||
getRgbBuffer: function DeviceGrayCS_getRgbBuffer(input, bits) {
|
||||
getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset,
|
||||
dest, destOffset) {
|
||||
var c = (src[srcOffset] * 255) | 0;
|
||||
c = c < 0 ? 0 : c > 255 ? 255 : c;
|
||||
dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
|
||||
},
|
||||
getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count,
|
||||
dest, destOffset, bits) {
|
||||
var scale = 255 / ((1 << bits) - 1);
|
||||
var length = input.length;
|
||||
var rgbBuf = new Uint8Array(length * 3);
|
||||
for (var i = 0, j = 0; i < length; ++i) {
|
||||
var c = (scale * input[i]) | 0;
|
||||
rgbBuf[j++] = c;
|
||||
rgbBuf[j++] = c;
|
||||
rgbBuf[j++] = c;
|
||||
var j = srcOffset, q = destOffset;
|
||||
for (var i = 0; i < count; ++i) {
|
||||
var c = (scale * src[j++]) | 0;
|
||||
dest[q++] = c;
|
||||
dest[q++] = c;
|
||||
dest[q++] = c;
|
||||
}
|
||||
return rgbBuf;
|
||||
},
|
||||
getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) {
|
||||
return inputLength * 3;
|
||||
},
|
||||
isPassthrough: ColorSpace.prototype.isPassthrough,
|
||||
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
|
||||
isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
|
||||
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
|
||||
}
|
||||
|
@ -12395,22 +12496,43 @@ var DeviceRgbCS = (function DeviceRgbCSClosure() {
|
|||
function DeviceRgbCS() {
|
||||
this.name = 'DeviceRGB';
|
||||
this.numComps = 3;
|
||||
this.defaultColor = [0, 0, 0];
|
||||
this.defaultColor = new Float32Array([0, 0, 0]);
|
||||
}
|
||||
DeviceRgbCS.prototype = {
|
||||
getRgb: function DeviceRgbCS_getRgb(color) {
|
||||
return color;
|
||||
getRgb: function DeviceRgbCS_getRgb(src, srcOffset) {
|
||||
var rgb = new Uint8Array(3);
|
||||
this.getRgbItem(src, srcOffset, rgb, 0);
|
||||
return rgb;
|
||||
},
|
||||
getRgbBuffer: function DeviceRgbCS_getRgbBuffer(input, bits) {
|
||||
if (bits == 8)
|
||||
return input;
|
||||
getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset,
|
||||
dest, destOffset) {
|
||||
var r = src[srcOffset] * 255;
|
||||
var g = src[srcOffset + 1] * 255;
|
||||
var b = src[srcOffset + 2] * 255;
|
||||
dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r;
|
||||
dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g;
|
||||
dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b;
|
||||
},
|
||||
getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count,
|
||||
dest, destOffset, bits) {
|
||||
var length = count * 3;
|
||||
if (bits == 8) {
|
||||
dest.set(src.subarray(srcOffset, srcOffset + length), destOffset);
|
||||
return;
|
||||
}
|
||||
var scale = 255 / ((1 << bits) - 1);
|
||||
var i, length = input.length;
|
||||
var rgbBuf = new Uint8Array(length);
|
||||
for (i = 0; i < length; ++i)
|
||||
rgbBuf[i] = (scale * input[i]) | 0;
|
||||
return rgbBuf;
|
||||
var j = srcOffset, q = destOffset;
|
||||
for (var i = 0; i < length; ++i) {
|
||||
dest[q++] = (scale * input[j++]) | 0;
|
||||
}
|
||||
},
|
||||
getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) {
|
||||
return inputLength;
|
||||
},
|
||||
isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
|
||||
return bits == 8;
|
||||
},
|
||||
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
|
||||
isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
|
||||
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
|
||||
}
|
||||
|
@ -13088,13 +13210,7 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() {
|
|||
15, 13, 26, 2, 1, 11, 0, 0, 0, 0, 0, 0, 54, 54, 57, 47, 44, 47, 39, 35, 39,
|
||||
28, 25, 29, 17, 13, 17, 4, 1, 3, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
function DeviceCmykCS() {
|
||||
this.name = 'DeviceCMYK';
|
||||
this.numComps = 4;
|
||||
this.defaultColor = [0, 0, 0, 1];
|
||||
}
|
||||
DeviceCmykCS.prototype = {
|
||||
getRgb: function DeviceCmykCS_getRgb(color) {
|
||||
function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
|
||||
// using lut as in spline interpolation (see function.js)
|
||||
var cubeVertices = 16; // 1 << number of colors
|
||||
var cubeN = new Float32Array(cubeVertices);
|
||||
|
@ -13105,7 +13221,7 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() {
|
|||
var k = 3, pos = 1;
|
||||
var lutDomain = 7, lutStep = 8;
|
||||
for (var i = 3; i >= 0; i--) {
|
||||
var e = color[i] * lutDomain;
|
||||
var e = src[srcOffset + i] * srcScale * lutDomain;
|
||||
|
||||
var e0 = e < lutDomain ? Math.floor(e) : e - 1; // e1 = e0 + 1;
|
||||
var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
|
||||
|
@ -13125,35 +13241,47 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() {
|
|||
k *= lutStep;
|
||||
pos <<= 1;
|
||||
}
|
||||
var y = new Float32Array(3);
|
||||
for (var j = 0; j < 3; ++j) {
|
||||
var rj = 0;
|
||||
var y0 = 0, y1 = 0, y2 = 0;
|
||||
for (var i = 0; i < cubeVertices; i++)
|
||||
rj += lut[cubeVertex[i] + j] * cubeN[i];
|
||||
y[j] = rj;
|
||||
y0 += lut[cubeVertex[i]] * cubeN[i];
|
||||
for (var i = 0; i < cubeVertices; i++)
|
||||
y1 += lut[cubeVertex[i] + 1] * cubeN[i];
|
||||
for (var i = 0; i < cubeVertices; i++)
|
||||
y2 += lut[cubeVertex[i] + 2] * cubeN[i];
|
||||
dest[destOffset] = y0 > 255 ? 255 : y0;
|
||||
dest[destOffset + 1] = y1 > 255 ? 255 : y1;
|
||||
dest[destOffset + 2] = y2 > 255 ? 255 : y2;
|
||||
}
|
||||
|
||||
return [y[0] / 255, y[1] / 255, y[2] / 255];
|
||||
function DeviceCmykCS() {
|
||||
this.name = 'DeviceCMYK';
|
||||
this.numComps = 4;
|
||||
this.defaultColor = new Float32Array([0, 0, 0, 1]);
|
||||
}
|
||||
DeviceCmykCS.prototype = {
|
||||
getRgb: function DeviceCmykCS_getRgb(src, srcOffset) {
|
||||
var rgb = new Uint8Array(3);
|
||||
convertToRgb(src, srcOffset, 1, rgb, 0);
|
||||
return rgb;
|
||||
},
|
||||
getRgbBuffer: function DeviceCmykCS_getRgbBuffer(colorBuf, bits) {
|
||||
getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset,
|
||||
dest, destOffset) {
|
||||
convertToRgb(src, srcOffset, 1, dest, destOffset);
|
||||
},
|
||||
getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count,
|
||||
dest, destOffset, bits) {
|
||||
var scale = 1 / ((1 << bits) - 1);
|
||||
var length = colorBuf.length / 4;
|
||||
var rgbBuf = new Uint8Array(length * 3);
|
||||
var rgbBufPos = 0;
|
||||
var colorBufPos = 0;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
var cmyk = [];
|
||||
for (var j = 0; j < 4; ++j)
|
||||
cmyk.push(scale * colorBuf[colorBufPos++]);
|
||||
|
||||
var rgb = this.getRgb(cmyk);
|
||||
for (var j = 0; j < 3; ++j)
|
||||
rgbBuf[rgbBufPos++] = Math.round(rgb[j] * 255);
|
||||
for (var i = 0; i < count; i++) {
|
||||
convertToRgb(src, srcOffset, scale, dest, destOffset);
|
||||
srcOffset += 4;
|
||||
destOffset += 3;
|
||||
}
|
||||
|
||||
return rgbBuf;
|
||||
},
|
||||
getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) {
|
||||
return (inputLength >> 2) * 3;
|
||||
},
|
||||
isPassthrough: ColorSpace.prototype.isPassthrough,
|
||||
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
|
||||
isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
|
||||
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
|
||||
}
|
||||
|
@ -13169,7 +13297,7 @@ var LabCS = (function LabCSClosure() {
|
|||
function LabCS(whitePoint, blackPoint, range) {
|
||||
this.name = 'Lab';
|
||||
this.numComps = 3;
|
||||
this.defaultColor = [0, 0, 0];
|
||||
this.defaultColor = new Float32Array([0, 0, 0]);
|
||||
|
||||
if (!whitePoint)
|
||||
error('WhitePoint missing - required for color space Lab');
|
||||
|
@ -13210,58 +13338,66 @@ var LabCS = (function LabCSClosure() {
|
|||
};
|
||||
|
||||
// Function g(x) from spec
|
||||
function g(x) {
|
||||
function fn_g(x) {
|
||||
if (x >= 6 / 29)
|
||||
return x * x * x;
|
||||
else
|
||||
return (108 / 841) * (x - 4 / 29);
|
||||
}
|
||||
|
||||
LabCS.prototype = {
|
||||
getRgb: function LabCS_getRgb(color) {
|
||||
function convertToRgb(cs, src, srcOffset, dest, destOffset) {
|
||||
// Ls,as,bs <---> L*,a*,b* in the spec
|
||||
var Ls = color[0], as = color[1], bs = color[2];
|
||||
var Ls = src[srcOffset];
|
||||
var as = src[srcOffset + 1];
|
||||
var bs = src[srcOffset + 2];
|
||||
|
||||
// Adjust limits of 'as' and 'bs'
|
||||
as = as > this.amax ? this.amax : as;
|
||||
as = as < this.amin ? this.amin : as;
|
||||
bs = bs > this.bmax ? this.bmax : bs;
|
||||
bs = bs < this.bmin ? this.bmin : bs;
|
||||
as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
|
||||
bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
|
||||
|
||||
// Computes intermediate variables X,Y,Z as per spec
|
||||
var M = (Ls + 16) / 116;
|
||||
var L = M + (as / 500);
|
||||
var N = M - (bs / 200);
|
||||
var X = this.XW * g(L);
|
||||
var Y = this.YW * g(M);
|
||||
var Z = this.ZW * g(N);
|
||||
|
||||
// XYZ to RGB 3x3 matrix, from:
|
||||
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
|
||||
var XYZtoRGB = [3.240479, -1.537150, -0.498535,
|
||||
-0.969256, 1.875992, 0.041556,
|
||||
0.055648, -0.204043, 1.057311];
|
||||
var X = cs.XW * fn_g(L);
|
||||
var Y = cs.YW * fn_g(M);
|
||||
var Z = cs.ZW * fn_g(N);
|
||||
|
||||
return Util.apply3dTransform(XYZtoRGB, [X, Y, Z]);
|
||||
},
|
||||
getRgbBuffer: function LabCS_getRgbBuffer(input, bits) {
|
||||
if (bits == 8)
|
||||
return input;
|
||||
var scale = 255 / ((1 << bits) - 1);
|
||||
var i, length = input.length / 3;
|
||||
var rgbBuf = new Uint8Array(length);
|
||||
|
||||
var j = 0;
|
||||
for (i = 0; i < length; ++i) {
|
||||
// Convert L*, a*, s* into RGB
|
||||
var rgb = this.getRgb([input[i], input[i + 1], input[i + 2]]);
|
||||
rgbBuf[j++] = rgb[0];
|
||||
rgbBuf[j++] = rgb[1];
|
||||
rgbBuf[j++] = rgb[2];
|
||||
var r, g, b;
|
||||
// Using different conversions for D50 and D65 white points,
|
||||
// per http://www.color.org/srgb.pdf
|
||||
if (cs.ZW < 1) {
|
||||
// Assuming D50 (X=0.9642, Y=1.00, Z=0.8249)
|
||||
r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
|
||||
g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
|
||||
b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
|
||||
} else {
|
||||
// Assuming D65 (X=0.9505, Y=1.00, Z=1.0888)
|
||||
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
|
||||
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
|
||||
b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
|
||||
}
|
||||
|
||||
return rgbBuf;
|
||||
// clamp color values to [0,255] range
|
||||
dest[destOffset] = r < 0 ? 0 : r > 1 ? 255 : r * 255;
|
||||
dest[destOffset + 1] = g < 0 ? 0 : g > 1 ? 255 : g * 255;
|
||||
dest[destOffset + 2] = b < 0 ? 0 : b > 1 ? 255 : b * 255;
|
||||
}
|
||||
|
||||
LabCS.prototype = {
|
||||
getRgb: function LabCS_getRgb(src, srcOffset) {
|
||||
var rgb = new Uint8Array(3);
|
||||
convertToRgb(this, src, srcOffset, rgb, 0);
|
||||
return rgb;
|
||||
},
|
||||
getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) {
|
||||
convertToRgb(this, src, srcOffset, dest, destOffset);
|
||||
},
|
||||
getOutputLength: function LabCS_getOutputLength(inputLength) {
|
||||
return inputLength;
|
||||
},
|
||||
isPassthrough: ColorSpace.prototype.isPassthrough,
|
||||
isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
|
||||
// From Table 90 in Adobe's:
|
||||
// "Document management - Portable document format", 1st ed, 2008
|
||||
|
@ -26097,8 +26233,8 @@ var PDFImage = (function PDFImageClosure() {
|
|||
var actualHeight = 0 | (imgArray.length / rowBytes *
|
||||
height / originalHeight);
|
||||
|
||||
var comps = this.colorSpace.getRgbBuffer(
|
||||
this.getComponents(imgArray), bpc);
|
||||
var comps = this.colorSpace.createRgbBuffer(this.getComponents(imgArray),
|
||||
0, originalWidth * originalHeight, bpc);
|
||||
if (originalWidth != width || originalHeight != height)
|
||||
comps = PDFImage.resize(comps, this.bpc, 3, originalWidth,
|
||||
originalHeight, width, height);
|
||||
|
@ -29850,11 +29986,29 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||
this.extendEnd = extendEnd;
|
||||
|
||||
var fnObj = dict.get('Function');
|
||||
if (isArray(fnObj))
|
||||
error('No support for array of functions');
|
||||
if (!isPDFFunction(fnObj))
|
||||
var fn;
|
||||
if (isArray(fnObj)) {
|
||||
var fnArray = [];
|
||||
for (var j = 0, jj = fnObj.length; j < jj; j++) {
|
||||
var obj = xref.fetchIfRef(fnObj[j]);
|
||||
if (!isPDFFunction(obj)) {
|
||||
error('Invalid function');
|
||||
var fn = PDFFunction.parse(xref, fnObj);
|
||||
}
|
||||
fnArray.push(PDFFunction.parse(xref, obj));
|
||||
}
|
||||
fn = function radialAxialColorFunction(arg) {
|
||||
var out = [];
|
||||
for (var i = 0, ii = fnArray.length; i < ii; i++) {
|
||||
out.push(fnArray[i](arg)[0]);
|
||||
}
|
||||
return out;
|
||||
};
|
||||
} else {
|
||||
if (!isPDFFunction(fnObj)) {
|
||||
error('Invalid function');
|
||||
}
|
||||
fn = PDFFunction.parse(xref, fnObj);
|
||||
}
|
||||
|
||||
// 10 samples seems good enough for now, but probably won't work
|
||||
// if there are sharp color changes. Ideally, we would implement
|
||||
|
@ -29873,15 +30027,15 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||
}
|
||||
|
||||
for (var i = t0; i <= t1; i += step) {
|
||||
var rgbColor = cs.getRgb(fn([i]));
|
||||
var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
|
||||
var rgbColor = cs.getRgb(fn([i]), 0);
|
||||
var cssColor = Util.makeCssRgb(rgbColor);
|
||||
colorStops.push([(i - t0) / diff, cssColor]);
|
||||
}
|
||||
|
||||
var background = 'transparent';
|
||||
if (dict.has('Background')) {
|
||||
var rgbColor = cs.getRgb(dict.get('Background'));
|
||||
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
|
||||
var rgbColor = cs.getRgb(dict.get('Background'), 0);
|
||||
background = Util.makeCssRgb(rgbColor);
|
||||
}
|
||||
|
||||
if (!extendStart) {
|
||||
|
@ -30029,7 +30183,8 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||
tmpCtx.strokeStyle = ctx.strokeStyle;
|
||||
break;
|
||||
case PaintType.UNCOLORED:
|
||||
var cssColor = Util.makeCssRgb(this, color[0], color[1], color[2]);
|
||||
var rgbColor = new DeviceRgbCS().getRgb(color, 0);
|
||||
var cssColor = Util.makeCssRgb(rgbColor);
|
||||
tmpCtx.fillStyle = cssColor;
|
||||
tmpCtx.strokeStyle = cssColor;
|
||||
break;
|
||||
|
|
|
@ -32,7 +32,6 @@ limitations under the License.
|
|||
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" src="debugger.js"></script>
|
||||
<script type="text/javascript" src="viewer.js"></script>
|
||||
</head>
|
||||
|
|
|
@ -681,11 +681,11 @@ var PDFFindBar = {
|
|||
|
||||
case FindStates.FIND_WRAPPED:
|
||||
if (previous) {
|
||||
findMsg = mozL10n.get('find_wrapped_to_bottom', null,
|
||||
'Reached top of page, continued from bottom');
|
||||
findMsg = mozL10n.get('find_reached_top', null,
|
||||
'Reached top of document, continued from bottom');
|
||||
} else {
|
||||
findMsg = mozL10n.get('find_wrapped_to_top', null,
|
||||
'Reached end of page, continued from top');
|
||||
findMsg = mozL10n.get('find_reached_bottom', null,
|
||||
'Reached end of document, continued from top');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -966,14 +966,18 @@ var PDFView = {
|
|||
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
|
||||
this.url = url;
|
||||
try {
|
||||
document.title = decodeURIComponent(getFileName(url)) || url;
|
||||
this.setTitle(decodeURIComponent(getFileName(url)) || url);
|
||||
} catch (e) {
|
||||
// decodeURIComponent may throw URIError,
|
||||
// fall back to using the unprocessed url in that case
|
||||
document.title = url;
|
||||
this.setTitle(url);
|
||||
}
|
||||
},
|
||||
|
||||
setTitle: function pdfViewSetTitle(title) {
|
||||
document.title = title;
|
||||
},
|
||||
|
||||
open: function pdfViewOpen(url, scale, password) {
|
||||
var parameters = {password: password};
|
||||
if (typeof url === 'string') { // URL
|
||||
|
@ -1286,6 +1290,11 @@ var PDFView = {
|
|||
self.documentInfo = info;
|
||||
self.metadata = metadata;
|
||||
|
||||
// Provides some basic debug information
|
||||
console.log('PDF ' + pdfDocument.fingerprint + ' [' +
|
||||
info.PDFFormatVersion + ' ' + (info.Producer || '-') +
|
||||
' / ' + (info.Creator || '-') + ']');
|
||||
|
||||
var pdfTitle;
|
||||
if (metadata) {
|
||||
if (metadata.has('dc:title'))
|
||||
|
@ -1296,7 +1305,7 @@ var PDFView = {
|
|||
pdfTitle = info['Title'];
|
||||
|
||||
if (pdfTitle)
|
||||
document.title = pdfTitle + ' - ' + document.title;
|
||||
self.setTitle(pdfTitle + ' - ' + document.title);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -2986,7 +2995,7 @@ function selectScaleOption(value) {
|
|||
}
|
||||
|
||||
window.addEventListener('localized', function localized(evt) {
|
||||
document.getElementsByTagName('html')[0].dir = mozL10n.language.direction;
|
||||
document.getElementsByTagName('html')[0].dir = mozL10n.getDirection();
|
||||
}, true);
|
||||
|
||||
window.addEventListener('scalechange', function scalechange(evt) {
|
||||
|
|
|
@ -704,7 +704,6 @@ uninstall/UninstallDeerPark.exe
|
|||
uninstall/UninstallFirefox.exe
|
||||
uninstall/uninst.exe
|
||||
uninstall/uninstall.exe
|
||||
update.locale
|
||||
#ifndef MOZ_UPDATER
|
||||
#ifdef XP_MACOSX
|
||||
updater.app/
|
||||
|
@ -715,6 +714,7 @@ update.locale
|
|||
#endif
|
||||
xpicleanup@BIN_SUFFIX@
|
||||
#ifdef MOZ_OMNIJAR
|
||||
update.locale
|
||||
omni.jar
|
||||
chrome/af.jar
|
||||
chrome/af.manifest
|
||||
|
|
|
@ -8,16 +8,27 @@
|
|||
<!ENTITY privatebrowsingpage.issueDesc "&brandShortName; won't remember any history for this session.">
|
||||
<!ENTITY privatebrowsingpage.issueDesc.normal "&brandShortName; is not currently in Private Browsing mode.">
|
||||
|
||||
<!ENTITY privatebrowsingpage.perwindow.issueDesc "&brandShortName; won't remember any history for this window.">
|
||||
<!ENTITY privatebrowsingpage.perwindow.issueDesc.normal "You are not currently in a private window.">
|
||||
|
||||
<!ENTITY privatebrowsingpage.description "In a Private Browsing session, &brandShortName; won't keep any browser history, search history, download history, web form history, cookies, or temporary internet files. However, files you download and bookmarks you make will be kept.">
|
||||
|
||||
<!ENTITY privatebrowsingpage.perwindow.description "In a Private Browsing window, &brandShortName; won't keep any browser history, search history, download history, web form history, cookies, or temporary internet files. However, files you download and bookmarks you make will be kept.">
|
||||
|
||||
<!ENTITY privatebrowsingpage.startPrivateBrowsing.label "Start Private Browsing">
|
||||
<!ENTITY privatebrowsingpage.startPrivateBrowsing.accesskey "P">
|
||||
|
||||
<!ENTITY privatebrowsingpage.openPrivateWindow.label "Open a Private Window">
|
||||
<!ENTITY privatebrowsingpage.openPrivateWindow.accesskey "P">
|
||||
|
||||
<!-- LOCALIZATION NOTE (privatebrowsingpage.howToStop2): please leave &basePBMenu.label; intact in the translation -->
|
||||
<!-- LOCALIZATION NOTE (privatebrowsingpage.howToStart2): please leave &basePBMenu.label; intact in the translation -->
|
||||
<!ENTITY privatebrowsingpage.howToStop2 "To stop Private Browsing, select &basePBMenu.label; > &privateBrowsingCmd.stop.label;, or close &brandShortName;.">
|
||||
<!ENTITY privatebrowsingpage.howToStart2 "To start Private Browsing, you can also select &basePBMenu.label; > &privateBrowsingCmd.start.label;.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (privatebrowsingpage.howToStart3): please leave &basePBMenu.label; intact in the translation -->
|
||||
<!ENTITY privatebrowsingpage.howToStart3 "To start Private Browsing, you can also select &basePBMenu.label; > &newPrivateWindow.label;.">
|
||||
<!ENTITY privatebrowsingpage.howToStop3 "To stop Private Browsing, you can close this window.">
|
||||
|
||||
<!ENTITY privatebrowsingpage.moreInfo "While this computer won't have a record of your browsing history, your internet service provider or employer can still track the pages you visit.">
|
||||
<!ENTITY privatebrowsingpage.learnMore "Learn More">
|
||||
|
|
|
@ -586,8 +586,6 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
|||
|
||||
<!ENTITY identity.moreInfoLinkText "More Information…">
|
||||
|
||||
<!ENTITY downloadMonitor2.tooltip "Click to open downloads window">
|
||||
|
||||
<!ENTITY allTabs.filter.emptyText "Search Tabs">
|
||||
<!-- Name for the tabs toolbar as spoken by screen readers.
|
||||
The word "toolbar" is appended automatically and should not be contained below! -->
|
||||
|
|
|
@ -232,14 +232,6 @@ identity.unknown.tooltip=This website does not supply identity information.
|
|||
|
||||
identity.ownerUnknown2=(unknown)
|
||||
|
||||
# Downloads Monitor Panel
|
||||
# LOCALIZATION NOTE (activeDownloads1, pausedDownloads1): Semi-colon list of plural
|
||||
# forms. See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 number of downloads; #2 time left
|
||||
# examples: 1 active download (2 minutes remaining); 11 paused downloads
|
||||
activeDownloads1=1 active download (#2);#1 active downloads (#2)
|
||||
pausedDownloads1=1 paused download;#1 paused downloads
|
||||
|
||||
# Edit Bookmark UI
|
||||
editBookmarkPanel.pageBookmarkedTitle=Page Bookmarked
|
||||
editBookmarkPanel.pageBookmarkedDescription=%S will always remember this page for you.
|
||||
|
|
|
@ -78,8 +78,8 @@ find_next.title=Find the next occurrence of the phrase
|
|||
find_next_label=Next
|
||||
find_highlight=Highlight all
|
||||
find_match_case_label=Match case
|
||||
find_wrapped_to_bottom=Reached top of page, continued from bottom
|
||||
find_wrapped_to_top=Reached end of page, continued from top
|
||||
find_reached_top=Reached top of document, continued from bottom
|
||||
find_reached_bottom=Reached end of document, continued from top
|
||||
find_not_found=Phrase not found
|
||||
|
||||
# Error panel labels
|
||||
|
|
|
@ -501,6 +501,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
|
|||
}
|
||||
|
||||
#appmenu_privateBrowsing,
|
||||
#appmenu_newPrivateWindow,
|
||||
#privateBrowsingItem {
|
||||
list-style-image: url("chrome://browser/skin/Privacy-16.png");
|
||||
}
|
||||
|
@ -1790,12 +1791,6 @@ toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon {
|
|||
display: -moz-box; /* display chevron icon in text mode */
|
||||
}
|
||||
|
||||
#download-monitor {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
|
||||
-moz-image-region: rect(0px 16px 16px 0px);
|
||||
}
|
||||
|
||||
|
||||
/* ::::: Keyboard UI Panel ::::: */
|
||||
|
||||
.KUI-panel-closebutton {
|
||||
|
|
|
@ -3130,10 +3130,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
@hudButtonPressed@
|
||||
}
|
||||
|
||||
#download-monitor {
|
||||
list-style-image: url("chrome://mozapps/skin/downloads/downloadStatusIcon.png");
|
||||
}
|
||||
|
||||
/* ::::: Keyboard UI Panel ::::: */
|
||||
|
||||
.KUI-panel {
|
||||
|
|
|
@ -416,7 +416,8 @@
|
|||
-moz-image-region: rect(0px 48px 16px 32px);
|
||||
}
|
||||
|
||||
#appmenu_privateBrowsing {
|
||||
#appmenu_privateBrowsing,
|
||||
#appmenu_newPrivateWindow {
|
||||
list-style-image: url("chrome://browser/skin/Privacy-16.png");
|
||||
}
|
||||
|
||||
|
@ -2407,11 +2408,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
|||
min-width: 280px;
|
||||
}
|
||||
|
||||
#download-monitor {
|
||||
list-style-image: url("chrome://browser/skin/Toolbar.png");
|
||||
-moz-image-region: rect(0, 108px, 18px, 90px);
|
||||
}
|
||||
|
||||
/* Bookmarks roots menu-items */
|
||||
#appmenu_subscribeToPage:not([disabled]),
|
||||
#appmenu_subscribeToPageMenu,
|
||||
|
|
|
@ -12,7 +12,7 @@ RANLIB=ranlib
|
|||
AR=ar
|
||||
AS=$CC
|
||||
LD=ld
|
||||
STRIP="strip -x -S"
|
||||
STRIP="strip"
|
||||
|
||||
MOZ_CAN_RUN_PROGRAMS=1
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
|
|||
AR=ar
|
||||
AS=$CC
|
||||
LD=ld
|
||||
STRIP="strip -x -S"
|
||||
STRIP="strip"
|
||||
|
||||
# Let configure know that we mean business.
|
||||
if test "$NATIVE_CPU" != "$TARGET_CPU" ; then
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
llvm_revision = "168596"
|
||||
llvm_revision = "169139"
|
||||
moz_version = "moz0"
|
||||
|
||||
##############################################
|
||||
|
|
43
configure.in
43
configure.in
|
@ -5254,6 +5254,20 @@ if test -n "$MOZ_WEBRTC"; then
|
|||
MOZ_VP8=1
|
||||
MOZ_VP8_ENCODER=1
|
||||
MOZ_VP8_ERROR_CONCEALMENT=1
|
||||
|
||||
dnl OpenSLES is only available in Android 2.3 and later; we'll change this
|
||||
dnl hard dependency to a dynamic load with graceful runtime failure before
|
||||
dnl we make --enable-webrtc on by default in Android (bug 815905)
|
||||
dnl
|
||||
if test "$OS_TARGET" = "Android"; then
|
||||
LDFLAGS="$LDFLAGS -lOpenSLES"
|
||||
fi
|
||||
case "$target" in
|
||||
*-android*|*-linuxandroid*)
|
||||
LDFLAGS="$LDFLAGS -lOpenSLES"
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl enable once Signaling lands
|
||||
MOZ_WEBRTC_SIGNALING=1
|
||||
AC_DEFINE(MOZ_WEBRTC_SIGNALING)
|
||||
|
@ -5270,6 +5284,7 @@ dnl enable once PeerConnection lands
|
|||
fi
|
||||
|
||||
AC_SUBST(MOZ_WEBRTC)
|
||||
AC_SUBST(MOZ_WEBRTC_LEAKING_TESTS)
|
||||
AC_SUBST(MOZ_WEBRTC_SIGNALING)
|
||||
AC_SUBST(MOZ_PEERCONNECTION)
|
||||
AC_SUBST(MOZ_WEBRTC_IN_LIBXUL)
|
||||
|
@ -8510,6 +8525,7 @@ fi
|
|||
|
||||
MOZ_B2G_VERSION=${MOZ_B2G_VERSION:-"1.0.0"}
|
||||
AC_DEFINE_UNQUOTED(MOZ_B2G_VERSION,"$MOZ_B2G_VERSION")
|
||||
AC_DEFINE_UNQUOTED(MOZ_B2G_OS_NAME,"$MOZ_B2G_OS_NAME")
|
||||
|
||||
AC_SUBST(MOZ_APP_NAME)
|
||||
AC_SUBST(MOZ_APP_DISPLAYNAME)
|
||||
|
@ -8851,6 +8867,28 @@ echo $MAKEFILES > unallmakefiles
|
|||
|
||||
AC_OUTPUT($MAKEFILES)
|
||||
|
||||
# target_arch is from {ia32|x64|arm}
|
||||
case "$CPU_ARCH" in
|
||||
x86_64 | ia64)
|
||||
WEBRTC_TARGET_ARCH=x64
|
||||
;;
|
||||
|
||||
arm*)
|
||||
WEBRTC_TARGET_ARCH=arm
|
||||
;;
|
||||
|
||||
x86)
|
||||
WEBRTC_TARGET_ARCH=ia32
|
||||
;;
|
||||
|
||||
*)
|
||||
# unsupported arch for webrtc
|
||||
WEBRTC_TARGET_ARCH=unknown
|
||||
MOZ_WEBRTC=
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Generate Makefiles for WebRTC directly from .gyp files
|
||||
if test "${OS_TARGET}" = "WINNT"; then
|
||||
if test "$HAVE_64BIT_OS"; then
|
||||
|
@ -8859,6 +8897,9 @@ if test "${OS_TARGET}" = "WINNT"; then
|
|||
OS_BITS=32
|
||||
fi
|
||||
EXTRA_GYP_DEFINES="-D MSVS_VERSION=${_MSVS_VERSION} -D MSVS_OS_BITS=${OS_BITS}"
|
||||
|
||||
elif test "${OS_TARGET}" = "Android"; then
|
||||
EXTRA_GYP_DEFINES="-D gtest_target_type=executable -D android_toolchain=${android_toolchain} -G os=android "
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_WEBRTC"; then
|
||||
|
@ -8868,7 +8909,7 @@ dnl Any --include files must also appear in -D FORCED_INCLUDE_FILE= entries
|
|||
dnl so that regeneration via dependencies works correctly
|
||||
WEBRTC_CONFIG="-D build_with_mozilla=1 --include ${srcdir}/media/webrtc/webrtc_config.gypi -D FORCED_INCLUDE_FILE=${srcdir}/media/webrtc/webrtc_config.gypi"
|
||||
|
||||
GYP_WEBRTC_OPTIONS="--format=mozmake ${WEBRTC_CONFIG} ${EXTRA_GYP_DEFINES} --depth=${srcdir}/media/webrtc/trunk --toplevel-dir=${srcdir} -G OBJDIR=${_objdir}"
|
||||
GYP_WEBRTC_OPTIONS="--format=mozmake ${WEBRTC_CONFIG} -D target_arch=${WEBRTC_TARGET_ARCH} ${EXTRA_GYP_DEFINES} --depth=${srcdir}/media/webrtc/trunk --toplevel-dir=${srcdir} -G OBJDIR=${_objdir}"
|
||||
|
||||
$PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium \
|
||||
$GYP_WEBRTC_OPTIONS \
|
||||
|
|
|
@ -1285,7 +1285,7 @@ public:
|
|||
* keep alive
|
||||
* @param aTracer the tracer for aScriptObject
|
||||
*/
|
||||
static nsresult HoldJSObjects(void* aScriptObjectHolder,
|
||||
static void HoldJSObjects(void* aScriptObjectHolder,
|
||||
nsScriptObjectTracer* aTracer);
|
||||
|
||||
/**
|
||||
|
@ -1294,7 +1294,7 @@ public:
|
|||
* @param aScriptObjectHolder the object that holds JS objects that we want to
|
||||
* drop
|
||||
*/
|
||||
static nsresult DropJSObjects(void* aScriptObjectHolder);
|
||||
static void DropJSObjects(void* aScriptObjectHolder);
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool AreJSObjectsHeld(void* aScriptObjectHolder);
|
||||
|
|
|
@ -2560,6 +2560,8 @@ Element::MozMatchesSelector(const nsAString& aSelector,
|
|||
nsRuleWalker::eRelevantLinkUnvisited,
|
||||
OwnerDoc(),
|
||||
TreeMatchContext::eNeverMatchVisited);
|
||||
matchingContext.SetHasSpecifiedScope();
|
||||
matchingContext.AddScopeElement(this);
|
||||
return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
|
||||
selectorList);
|
||||
}
|
||||
|
|
|
@ -4512,24 +4512,23 @@ nsContentUtils::DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent)
|
|||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
void
|
||||
nsContentUtils::HoldJSObjects(void* aScriptObjectHolder,
|
||||
nsScriptObjectTracer* aTracer)
|
||||
{
|
||||
NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
|
||||
MOZ_ASSERT(sXPConnect, "Tried to HoldJSObjects when there was no XPConnect");
|
||||
if (sXPConnect) {
|
||||
sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
void
|
||||
nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
|
||||
{
|
||||
if (!sXPConnect) {
|
||||
return NS_OK;
|
||||
if (sXPConnect) {
|
||||
sXPConnect->RemoveJSHolder(aScriptObjectHolder);
|
||||
}
|
||||
|
||||
return sXPConnect->RemoveJSHolder(aScriptObjectHolder);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -4537,9 +4536,7 @@ nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
|
|||
bool
|
||||
nsContentUtils::AreJSObjectsHeld(void* aScriptHolder)
|
||||
{
|
||||
bool isHeld = false;
|
||||
sXPConnect->TestJSHolder(aScriptHolder, &isHeld);
|
||||
return isHeld;
|
||||
return sXPConnect->TestJSHolder(aScriptHolder);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ nsDOMParser::ParseFromString(const nsAString& aStr, SupportedType aType,
|
|||
ErrorResult& rv)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDocument;
|
||||
rv = nsDOMParser::ParseFromString(PromiseFlatString(aStr).get(),
|
||||
rv = ParseFromString(aStr,
|
||||
SupportedTypeValues::strings[aType].value,
|
||||
getter_AddRefs(domDocument));
|
||||
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
|
||||
|
@ -74,6 +74,16 @@ nsDOMParser::ParseFromString(const PRUnichar *str,
|
|||
nsIDOMDocument **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(str);
|
||||
// Converting a string to an enum value manually is a bit of a pain,
|
||||
// so let's just use a helper that takes a content-type string.
|
||||
return ParseFromString(nsDependentString(str), contentType, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMParser::ParseFromString(const nsAString& str,
|
||||
const char *contentType,
|
||||
nsIDOMDocument **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
nsresult rv;
|
||||
|
@ -96,8 +106,7 @@ nsDOMParser::ParseFromString(const PRUnichar *str,
|
|||
// And the right principal
|
||||
document->SetPrincipal(mPrincipal);
|
||||
|
||||
nsDependentString sourceBuffer(str);
|
||||
rv = nsContentUtils::ParseDocumentHTML(sourceBuffer, document, false);
|
||||
rv = nsContentUtils::ParseDocumentHTML(str, document, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
domDocument.forget(aResult);
|
||||
|
|
|
@ -89,6 +89,10 @@ private:
|
|||
|
||||
nsresult SetUpDocument(DocumentFlavor aFlavor, nsIDOMDocument** aResult);
|
||||
|
||||
// Helper for ParseFromString
|
||||
nsresult ParseFromString(const nsAString& str, const char *contentType,
|
||||
nsIDOMDocument **aResult);
|
||||
|
||||
class AttemptedInitMarker {
|
||||
public:
|
||||
AttemptedInitMarker(bool* aAttemptedInit) :
|
||||
|
|
|
@ -9496,6 +9496,8 @@ nsDocument::UpdateVisibilityState()
|
|||
NS_LITERAL_STRING("mozvisibilitychange"),
|
||||
/* bubbles = */ true,
|
||||
/* cancelable = */ false);
|
||||
|
||||
EnumerateFreezableElements(NotifyActivityChanged, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -570,6 +570,7 @@ GK_ATOM(mouseout, "mouseout")
|
|||
GK_ATOM(mouseover, "mouseover")
|
||||
GK_ATOM(mousethrough, "mousethrough")
|
||||
GK_ATOM(mouseup, "mouseup")
|
||||
GK_ATOM(mozaudiochannel, "mozaudiochannel")
|
||||
GK_ATOM(mozasyncpanzoom, "mozasyncpanzoom")
|
||||
GK_ATOM(mozfullscreenchange, "mozfullscreenchange")
|
||||
GK_ATOM(mozfullscreenerror, "mozfullscreenerror")
|
||||
|
|
|
@ -2198,6 +2198,16 @@ ParseSelectorList(nsINode* aNode,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
AddScopeElements(TreeMatchContext& aMatchContext,
|
||||
nsINode* aMatchContextNode)
|
||||
{
|
||||
if (aMatchContextNode->IsElement()) {
|
||||
aMatchContext.SetHasSpecifiedScope();
|
||||
aMatchContext.AddScopeElement(aMatchContextNode->AsElement());
|
||||
}
|
||||
}
|
||||
|
||||
// Actually find elements matching aSelectorList (which must not be
|
||||
// null) and which are descendants of aRoot and put them in aList. If
|
||||
// onlyFirstMatch, then stop once the first one is found.
|
||||
|
@ -2218,6 +2228,7 @@ FindMatchingElements(nsINode* aRoot, const nsAString& aSelector, T &aList)
|
|||
TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
|
||||
doc, TreeMatchContext::eNeverMatchVisited);
|
||||
doc->FlushPendingLinkUpdates();
|
||||
AddScopeElements(matchingContext, aRoot);
|
||||
|
||||
// Fast-path selectors involving IDs. We can only do this if aRoot
|
||||
// is in the document and the document is not in quirks mode, since
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsIDOMHTMLScriptElement.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
@ -257,7 +258,8 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
|
||||
nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
|
||||
bool aScriptFromHead)
|
||||
{
|
||||
nsISupports *context = aRequest->mElement.get()
|
||||
? static_cast<nsISupports *>(aRequest->mElement.get())
|
||||
|
@ -302,6 +304,15 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
|
|||
channelPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIScriptElement *script = aRequest->mElement;
|
||||
if (aScriptFromHead &&
|
||||
!(script && (script->GetScriptAsync() || script->GetScriptDeferred()))) {
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(channel));
|
||||
if (internalHttpChannel)
|
||||
internalHttpChannel->SetLoadAsBlocking(true);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
// HTTP content negotation has little value in this context.
|
||||
|
@ -518,7 +529,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
|||
request->mURI = scriptURI;
|
||||
request->mIsInline = false;
|
||||
request->mLoading = true;
|
||||
rv = StartLoad(request, type);
|
||||
|
||||
// set aScriptFromHead to false so we don't treat non preloaded scripts as
|
||||
// blockers for full page load. See bug 792438.
|
||||
rv = StartLoad(request, type, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Asynchronously report the load failure
|
||||
NS_DispatchToCurrentThread(
|
||||
|
@ -1236,7 +1250,8 @@ nsScriptLoader::ParsingComplete(bool aTerminated)
|
|||
void
|
||||
nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||
const nsAString &aType,
|
||||
const nsAString &aCrossOrigin)
|
||||
const nsAString &aCrossOrigin,
|
||||
bool aScriptFromHead)
|
||||
{
|
||||
// Check to see if scripts has been turned off.
|
||||
if (!mEnabled || !mDocument->IsScriptEnabled()) {
|
||||
|
@ -1249,7 +1264,7 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
|||
request->mURI = aURI;
|
||||
request->mIsInline = false;
|
||||
request->mLoading = true;
|
||||
nsresult rv = StartLoad(request, aType);
|
||||
nsresult rv = StartLoad(request, aType, aScriptFromHead);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -200,10 +200,12 @@ public:
|
|||
* @param aType The type parameter for the script.
|
||||
* @param aCrossOrigin The crossorigin attribute for the script.
|
||||
* Void if not present.
|
||||
* @param aScriptFromHead Whether or not the script was a child of head
|
||||
*/
|
||||
virtual void PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||
const nsAString &aType,
|
||||
const nsAString &aCrossOrigin);
|
||||
const nsAString &aCrossOrigin,
|
||||
bool aScriptFromHead);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -228,7 +230,8 @@ private:
|
|||
/**
|
||||
* Start a load for aRequest's URI.
|
||||
*/
|
||||
nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType);
|
||||
nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
|
||||
bool aScriptFromHead);
|
||||
|
||||
/**
|
||||
* Process any pending requests asynchronously (i.e. off an event) if there
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
|
@ -2964,6 +2965,15 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
// the channel slow by default for pipeline purposes
|
||||
AddLoadFlags(mChannel, nsIRequest::INHIBIT_PIPELINE);
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(mChannel));
|
||||
if (internalHttpChannel) {
|
||||
// we never let XHR be blocked by head CSS/JS loads to avoid
|
||||
// potential deadlock where server generation of CSS/JS requires
|
||||
// an XHR signal.
|
||||
internalHttpChannel->SetLoadUnblocked(true);
|
||||
}
|
||||
|
||||
if (!IsSystemXHR()) {
|
||||
// Always create a nsCORSListenerProxy here even if it's
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
|
|
|
@ -267,6 +267,7 @@ MOCHITEST_FILES_A = \
|
|||
test_bug782342.html \
|
||||
test_bug282547.html \
|
||||
bug282547.sjs \
|
||||
test_domparser_null_char.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_FILES_B = \
|
||||
|
|
|
@ -100,6 +100,9 @@
|
|||
/* :root tests */
|
||||
:root { background-color: green; }
|
||||
|
||||
/* :-moz-scope tests */
|
||||
:-moz-scope { background-color: green; }
|
||||
|
||||
/* :nth-child(n) tests */
|
||||
.nthchild1 > :nth-last-child(odd) { background-color: lime; }
|
||||
.nthchild1 > :nth-child(odd) { background-color: lime; }
|
||||
|
@ -269,6 +272,9 @@
|
|||
cacheCheck( "Disconnected Element", root4 );
|
||||
runTest( ecss, "SyntaxError: Disconnected Element", root4, false );
|
||||
jqTests("Disconnected Element", root3.cloneNode(true), "querySelectorAll");
|
||||
var newRoot = document.createElement("nosuchtag");
|
||||
newRoot.appendChild(root3.cloneNode(true));
|
||||
jqTests("Disconnected Element scoping", newRoot, "querySelectorAll");
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
fragment.appendChild( root2.cloneNode(true) );
|
||||
|
@ -537,7 +543,9 @@
|
|||
|
||||
var namespaced = /\|[^=]/.test( q );
|
||||
var prepend = namespaced ? "xHTML|*#root3 " : "#root3 ";
|
||||
q = (restrict === false || restrict === ":root" ? "" : prepend) + q.replace(/,/g, ", " + prepend);
|
||||
q = (restrict === false || restrict === ":root" ||
|
||||
restrict === ":-moz-scope" ? "" : prepend) +
|
||||
q.replace(/,/g, ", " + prepend);
|
||||
var nq = q.replace(/>/g, ">").replace(/</g, "<");
|
||||
|
||||
if ( namespaced ) {
|
||||
|
@ -567,7 +575,10 @@
|
|||
assert( pass, type + ": " + name + " (" + nq + ")" +
|
||||
(pass ? "" : " Expected: " + extra(ids) + " Received: " + extra(results)) );
|
||||
|
||||
if (results)
|
||||
// For now, don't use checkMatchesSelector when
|
||||
// restrict === ":-moz-scope" because we have no way to hand the
|
||||
// right scope to it yet.
|
||||
if (results && restrict !== ":-moz-scope")
|
||||
checkMatchesSelector( results, q );
|
||||
}
|
||||
|
||||
|
@ -630,8 +641,15 @@
|
|||
|
||||
if ( root == document ) {
|
||||
t( ":root Selector", ":root", ["html"], false );
|
||||
t( ":-moz-scope Selector", ":-moz-scope", ["html"], ":-moz-scope" );
|
||||
} else {
|
||||
t( ":root Selector", ":root", [], ":root" );
|
||||
if (root.localName != "nosuchtag") {
|
||||
t( ":-moz-scope Selector", ":-moz-scope > nosuchtag",
|
||||
[ "outerbogustag" ], ":-moz-scope");
|
||||
}
|
||||
t( ":-moz-scope Selector", ":-moz-scope nosuchtag nosuchtag",
|
||||
[ "innerbogustag" ], ":-moz-scope");
|
||||
|
||||
if ( !root.parentNode ) {
|
||||
t( ":root All Selector", ":root *", [], ":root" );
|
||||
|
@ -641,6 +659,7 @@
|
|||
if ( root.parentNode || root == document ) {
|
||||
assert( query(":root *").length == query("*").length - (root == document ? 1 : 0), type + ": :root All Selector" );
|
||||
}
|
||||
assert( query(":-moz-scope *").length == query("*").length - (root == document ? 1 : 0), type + ": :-moz-scope All Selector" );
|
||||
|
||||
t( "Element Selector", "p", ["firstp","ap","sndp","en","sap","first"] );
|
||||
t( "Element Selector", "body", ["body"], false );
|
||||
|
@ -1259,6 +1278,10 @@
|
|||
|
||||
<div id="nothiddendivchild"></div>
|
||||
</div>
|
||||
<!-- Test for scoping -->
|
||||
<nosuchtag id="outerbogustag">
|
||||
<nosuchtag id="innerbogustag"></nosuchtag>
|
||||
</nosuchtag>
|
||||
<!-- this iframe is outside the #main so it won't reload constantly wasting time, but it means the tests must be "safe" and clean up after themselves -->
|
||||
<iframe id="loadediframe" name="loadediframe" style="display:none;" src="data/iframe.html"></iframe>
|
||||
<dl id="dl" style="display:none;">
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=817469
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 817469</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=817469">Mozilla Bug 817469</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 817469 **/
|
||||
var doc = new DOMParser().parseFromString("\x00<div id='myElement'>", "text/html");
|
||||
isnot(doc.getElementById("myElement"), null, "Should not stop at null");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -97,6 +97,8 @@
|
|||
#include "nsHTMLImageElement.h"
|
||||
#include "nsHTMLVideoElement.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
|
||||
#include <cstdlib> // for std::abs(int/long)
|
||||
#include <cmath> // for std::abs(float/double)
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
@ -3739,8 +3741,8 @@ CanvasRenderingContext2D::CreateImageData(JSContext* cx, double sw,
|
|||
int32_t wi = JS_DoubleToInt32(sw);
|
||||
int32_t hi = JS_DoubleToInt32(sh);
|
||||
|
||||
uint32_t w = NS_ABS(wi);
|
||||
uint32_t h = NS_ABS(hi);
|
||||
uint32_t w = std::abs(wi);
|
||||
uint32_t h = std::abs(hi);
|
||||
return mozilla::dom::CreateImageData(cx, this, w, h, error);
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,8 @@ static uint32_t CountNewlinesInNativeLength(nsIContent* aContent,
|
|||
}
|
||||
#endif
|
||||
|
||||
static uint32_t GetNativeTextLength(nsIContent* aContent, uint32_t aMaxLength = UINT32_MAX)
|
||||
/* static */ uint32_t
|
||||
nsContentEventHandler::GetNativeTextLength(nsIContent* aContent, uint32_t aMaxLength)
|
||||
{
|
||||
if (aContent->IsNodeOfType(nsINode::eTEXT)) {
|
||||
uint32_t textLengthDifference =
|
||||
|
@ -369,7 +370,7 @@ nsContentEventHandler::SetRangeFromFlatTextOffset(
|
|||
uint32_t aNativeLength,
|
||||
bool aExpandToClusterBoundaries)
|
||||
{
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
|
||||
nsresult rv = iter->Init(mRootContent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -80,6 +80,9 @@ public:
|
|||
static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
|
||||
nsRange* aRange,
|
||||
uint32_t* aOffset);
|
||||
// Get the native text length of a content node excluding any children
|
||||
static uint32_t GetNativeTextLength(nsIContent* aContent,
|
||||
uint32_t aMaxLength = UINT32_MAX);
|
||||
protected:
|
||||
// Make the DOM range from the offset of FlatText and the text length.
|
||||
// If aExpandToClusterBoundaries is true, the start offset and the end one are
|
||||
|
|
|
@ -100,6 +100,8 @@
|
|||
#include "sampler.h"
|
||||
|
||||
#include "nsIDOMClientRect.h"
|
||||
#include <cstdlib> // for std::abs(int/long)
|
||||
#include <cmath> // for std::abs(float/double)
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#import <ApplicationServices/ApplicationServices.h>
|
||||
|
@ -2070,8 +2072,8 @@ nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
|
|||
|
||||
// fire drag gesture if mouse has moved enough
|
||||
nsIntPoint pt = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
|
||||
if (NS_ABS(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
|
||||
NS_ABS(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
|
||||
if (std::abs(pt.x - mGestureDownPoint.x) > pixelThresholdX ||
|
||||
std::abs(pt.y - mGestureDownPoint.y) > pixelThresholdY) {
|
||||
if (mClickHoldContextMenu) {
|
||||
// stop the click-hold before we fire off the drag gesture, in case
|
||||
// it takes a long time
|
||||
|
@ -2895,14 +2897,14 @@ nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
|||
nsIntSize devPixelPageSize(pc->AppUnitsToDevPixels(pageSize.width),
|
||||
pc->AppUnitsToDevPixels(pageSize.height));
|
||||
if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedX(aEvent) &&
|
||||
NS_ABS(actualDevPixelScrollAmount.x) > devPixelPageSize.width) {
|
||||
std::abs(actualDevPixelScrollAmount.x) > devPixelPageSize.width) {
|
||||
actualDevPixelScrollAmount.x =
|
||||
(actualDevPixelScrollAmount.x >= 0) ? devPixelPageSize.width :
|
||||
-devPixelPageSize.width;
|
||||
}
|
||||
|
||||
if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedY(aEvent) &&
|
||||
NS_ABS(actualDevPixelScrollAmount.y) > devPixelPageSize.height) {
|
||||
std::abs(actualDevPixelScrollAmount.y) > devPixelPageSize.height) {
|
||||
actualDevPixelScrollAmount.y =
|
||||
(actualDevPixelScrollAmount.y >= 0) ? devPixelPageSize.height :
|
||||
-devPixelPageSize.height;
|
||||
|
@ -5556,7 +5558,7 @@ nsEventStateManager::WheelPrefs::IsOverOnePageScrollAllowedX(
|
|||
{
|
||||
Index index = GetIndexFor(aEvent);
|
||||
Init(index);
|
||||
return NS_ABS(mMultiplierX[index]) >=
|
||||
return std::abs(mMultiplierX[index]) >=
|
||||
MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
|
||||
}
|
||||
|
||||
|
@ -5566,6 +5568,6 @@ nsEventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
|
|||
{
|
||||
Index index = GetIndexFor(aEvent);
|
||||
Init(index);
|
||||
return NS_ABS(mMultiplierY[index]) >=
|
||||
return std::abs(mMultiplierY[index]) >=
|
||||
MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,8 @@ public:
|
|||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
|
||||
void Init(nsIWidget* aWidget,
|
||||
nsPresContext* aPresContext,
|
||||
|
@ -79,6 +81,7 @@ private:
|
|||
void ObserveEditableNode();
|
||||
|
||||
bool mObserving;
|
||||
uint32_t mPreAttrChangeLength;
|
||||
};
|
||||
|
||||
/******************************************************************/
|
||||
|
@ -976,6 +979,50 @@ nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
|
|||
new TextChangeEvent(this, offset, offset + childOffset, offset));
|
||||
}
|
||||
|
||||
static nsIContent*
|
||||
GetContentBR(mozilla::dom::Element *aElement) {
|
||||
if (!aElement->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIContent *content = static_cast<nsIContent*>(aElement);
|
||||
return content->IsHTML(nsGkAtoms::br) ? content : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextStateManager::AttributeWillChange(nsIDocument* aDocument,
|
||||
mozilla::dom::Element* aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
int32_t aModType)
|
||||
{
|
||||
nsIContent *content = GetContentBR(aElement);
|
||||
mPreAttrChangeLength = content ?
|
||||
nsContentEventHandler::GetNativeTextLength(content) : 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextStateManager::AttributeChanged(nsIDocument* aDocument,
|
||||
mozilla::dom::Element* aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
int32_t aModType)
|
||||
{
|
||||
nsIContent *content = GetContentBR(aElement);
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
uint32_t postAttrChangeLength =
|
||||
nsContentEventHandler::GetNativeTextLength(content);
|
||||
if (postAttrChangeLength != mPreAttrChangeLength) {
|
||||
uint32_t start;
|
||||
if (NS_SUCCEEDED(nsContentEventHandler::GetFlatTextOffsetOfRange(
|
||||
mRootContent, content, 0, &start))) {
|
||||
nsContentUtils::AddScriptRunner(new TextChangeEvent(this, start,
|
||||
start + mPreAttrChangeLength, start + postAttrChangeLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsIMEStateManager::IsEditable(nsINode* node)
|
||||
{
|
||||
|
|
|
@ -113,7 +113,7 @@ public:
|
|||
|
||||
/**
|
||||
* Call this to reevaluate whether we should start/stop due to our owner
|
||||
* document being active or inactive.
|
||||
* document being active, inactive, visible or hidden.
|
||||
*/
|
||||
void NotifyOwnerDocumentActivityChanged();
|
||||
|
||||
|
@ -326,6 +326,9 @@ public:
|
|||
return mSrcStream->GetStream();
|
||||
}
|
||||
|
||||
// Notification from the AudioChannelService.
|
||||
nsresult NotifyAudioChannelStateChanged();
|
||||
|
||||
protected:
|
||||
class MediaLoadListener;
|
||||
class StreamListener;
|
||||
|
@ -605,6 +608,15 @@ protected:
|
|||
return isPaused;
|
||||
}
|
||||
|
||||
// Check the permissions for audiochannel.
|
||||
bool CheckAudioChannelPermissions(const nsAString& aType);
|
||||
|
||||
// This method does the check for muting/unmuting the audio channel.
|
||||
nsresult UpdateChannelMuteState();
|
||||
|
||||
// Update the audio channel playing state
|
||||
void UpdateAudioChannelPlayingState();
|
||||
|
||||
// The current decoder. Load() has been called on this decoder.
|
||||
// At most one of mDecoder and mSrcStream can be non-null.
|
||||
nsRefPtr<MediaDecoder> mDecoder;
|
||||
|
@ -879,6 +891,12 @@ protected:
|
|||
|
||||
// Audio Channel Type.
|
||||
mozilla::dom::AudioChannelType mAudioChannelType;
|
||||
|
||||
// The audiochannel has been muted
|
||||
bool mChannelMuted;
|
||||
|
||||
// Is this media element playing?
|
||||
bool mPlayingThroughTheAudioChannel;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,11 +67,15 @@
|
|||
#include "nsHostObjectProtocolHandler.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
|
||||
#include "AudioChannelService.h"
|
||||
|
||||
#include "nsCSSParser.h"
|
||||
#include "nsIMediaList.h"
|
||||
|
||||
#include "ImageContainer.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
#include <cstdlib> // for std::abs(int/long)
|
||||
#include <cmath> // for std::abs(float/double)
|
||||
|
||||
#ifdef MOZ_OGG
|
||||
#include "OggDecoder.h"
|
||||
|
@ -115,6 +119,8 @@ static PRLogModuleInfo* gMediaElementEventsLog;
|
|||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "nsIPermissionManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
|
@ -460,6 +466,7 @@ NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Autoplay, autoplay)
|
|||
NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Loop, loop)
|
||||
NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, DefaultMuted, muted)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMediaElement, Preload, preload, NULL)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMediaElement, MozAudioChannelType, mozaudiochannel, "normal")
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLMediaElement::GetMozSrcObject(JSContext* aCtx, jsval *aParams)
|
||||
|
@ -1549,7 +1556,8 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMuted(bool *aMuted)
|
|||
|
||||
void nsHTMLMediaElement::SetMutedInternal(bool aMuted)
|
||||
{
|
||||
float effectiveVolume = aMuted ? 0.0f : float(mVolume);
|
||||
float effectiveVolume = aMuted || mChannelMuted ? 0.0f : float(mVolume);
|
||||
|
||||
if (mDecoder) {
|
||||
mDecoder->SetVolume(effectiveVolume);
|
||||
} else if (mAudioStream) {
|
||||
|
@ -1762,7 +1770,9 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
|||
mCORSMode(CORS_NONE),
|
||||
mHasAudio(false),
|
||||
mDownloadSuspendedByCache(false),
|
||||
mAudioChannelType(AUDIO_CHANNEL_NORMAL)
|
||||
mAudioChannelType(AUDIO_CHANNEL_NORMAL),
|
||||
mChannelMuted(false),
|
||||
mPlayingThroughTheAudioChannel(false)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gMediaElementLog) {
|
||||
|
@ -1943,6 +1953,17 @@ bool nsHTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
// Mappings from 'mozaudiochannel' attribute strings to an enumeration.
|
||||
static const nsAttrValue::EnumTable kMozAudioChannelAttributeTable[] = {
|
||||
{ "normal", AUDIO_CHANNEL_NORMAL },
|
||||
{ "content", AUDIO_CHANNEL_CONTENT },
|
||||
{ "notification", AUDIO_CHANNEL_NOTIFICATION },
|
||||
{ "alarm", AUDIO_CHANNEL_ALARM },
|
||||
{ "telephony", AUDIO_CHANNEL_TELEPHONY },
|
||||
{ "publicnotification", AUDIO_CHANNEL_PUBLICNOTIFICATION },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
if (ParseImageAttribute(aAttribute, aValue, aResult)) {
|
||||
return true;
|
||||
|
@ -1954,12 +1975,52 @@ bool nsHTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
|
|||
if (aAttribute == nsGkAtoms::preload) {
|
||||
return aResult.ParseEnumValue(aValue, kPreloadTable, false);
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::mozaudiochannel) {
|
||||
bool parsed = aResult.ParseEnumValue(aValue, kMozAudioChannelAttributeTable, false,
|
||||
&kMozAudioChannelAttributeTable[0]);
|
||||
if (!parsed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioChannelType audioChannelType = static_cast<AudioChannelType>(aResult.GetEnumValue());
|
||||
|
||||
if (audioChannelType != mAudioChannelType &&
|
||||
!mDecoder &&
|
||||
CheckAudioChannelPermissions(aValue)) {
|
||||
mAudioChannelType = audioChannelType;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
|
||||
aResult);
|
||||
}
|
||||
|
||||
bool nsHTMLMediaElement::CheckAudioChannelPermissions(const nsAString& aString)
|
||||
{
|
||||
#ifdef MOZ_B2G
|
||||
// Only normal channel doesn't need permission.
|
||||
if (!aString.EqualsASCII("normal")) {
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permissionManager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
|
||||
permissionManager->TestExactPermissionFromPrincipal(NodePrincipal(),
|
||||
nsCString(NS_LITERAL_CSTRING("audio-channel-") + NS_ConvertUTF16toUTF8(aString)).get(), &perm);
|
||||
if (perm != nsIPermissionManager::ALLOW_ACTION) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::DoneCreatingElement()
|
||||
{
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::muted))
|
||||
|
@ -2793,6 +2854,8 @@ void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
|
|||
nsMediaReadyState oldState = mReadyState;
|
||||
mReadyState = aState;
|
||||
|
||||
UpdateAudioChannelPlayingState();
|
||||
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY ||
|
||||
oldState == mReadyState) {
|
||||
return;
|
||||
|
@ -3037,6 +3100,10 @@ void nsHTMLMediaElement::NotifyOwnerDocumentActivityChanged()
|
|||
}
|
||||
}
|
||||
|
||||
if (mPlayingThroughTheAudioChannel) {
|
||||
UpdateChannelMuteState();
|
||||
}
|
||||
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
|
||||
|
@ -3075,6 +3142,8 @@ void nsHTMLMediaElement::AddRemoveSelfReference()
|
|||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAudioChannelPlayingState();
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::DoRemoveSelfReference()
|
||||
|
@ -3364,10 +3433,10 @@ static double ClampPlaybackRate(double aPlaybackRate)
|
|||
if (aPlaybackRate == 0.0) {
|
||||
return aPlaybackRate;
|
||||
}
|
||||
if (NS_ABS(aPlaybackRate) < MIN_PLAYBACKRATE) {
|
||||
if (std::abs(aPlaybackRate) < MIN_PLAYBACKRATE) {
|
||||
return aPlaybackRate < 0 ? -MIN_PLAYBACKRATE : MIN_PLAYBACKRATE;
|
||||
}
|
||||
if (NS_ABS(aPlaybackRate) > MAX_PLAYBACKRATE) {
|
||||
if (std::abs(aPlaybackRate) > MAX_PLAYBACKRATE) {
|
||||
return aPlaybackRate < 0 ? -MAX_PLAYBACKRATE : MAX_PLAYBACKRATE;
|
||||
}
|
||||
return aPlaybackRate;
|
||||
|
@ -3435,65 +3504,74 @@ NS_IMETHODIMP nsHTMLMediaElement::SetMozPreservesPitch(bool aPreservesPitch)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLMediaElement::GetMozAudioChannelType(nsAString& aString)
|
||||
{
|
||||
switch (mAudioChannelType) {
|
||||
case AUDIO_CHANNEL_NORMAL:
|
||||
aString.AssignLiteral("normal");
|
||||
break;
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
aString.AssignLiteral("content");
|
||||
break;
|
||||
case AUDIO_CHANNEL_NOTIFICATION:
|
||||
aString.AssignLiteral("notification");
|
||||
break;
|
||||
case AUDIO_CHANNEL_ALARM:
|
||||
aString.AssignLiteral("alarm");
|
||||
break;
|
||||
case AUDIO_CHANNEL_TELEPHONY:
|
||||
aString.AssignLiteral("telephony");
|
||||
break;
|
||||
case AUDIO_CHANNEL_PUBLICNOTIFICATION:
|
||||
aString.AssignLiteral("publicnotification");
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLMediaElement::SetMozAudioChannelType(const nsAString& aString)
|
||||
{
|
||||
AudioChannelType tmpType;
|
||||
|
||||
if (aString.EqualsASCII("normal")) {
|
||||
tmpType = AUDIO_CHANNEL_NORMAL;
|
||||
} else if (aString.EqualsASCII("content")) {
|
||||
tmpType = AUDIO_CHANNEL_CONTENT;
|
||||
} else if (aString.EqualsASCII("notification")) {
|
||||
tmpType = AUDIO_CHANNEL_NOTIFICATION;
|
||||
} else if (aString.EqualsASCII("alarm")) {
|
||||
tmpType = AUDIO_CHANNEL_ALARM;
|
||||
} else if (aString.EqualsASCII("telephony")) {
|
||||
tmpType = AUDIO_CHANNEL_TELEPHONY;
|
||||
} else if (aString.EqualsASCII("publicnotification")) {
|
||||
tmpType = AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (tmpType != mAudioChannelType && mDecoder) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mAudioChannelType = tmpType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ImageContainer* nsHTMLMediaElement::GetImageContainer()
|
||||
{
|
||||
VideoFrameContainer* container = GetVideoFrameContainer();
|
||||
return container ? container->GetImageContainer() : nullptr;
|
||||
}
|
||||
|
||||
nsresult nsHTMLMediaElement::UpdateChannelMuteState()
|
||||
{
|
||||
// Only on B2G we mute the nsHTMLMediaElement following the rules of
|
||||
// AudioChannelService.
|
||||
#ifdef MOZ_B2G
|
||||
bool hidden = false;
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(OwnerDoc());
|
||||
if (!domDoc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = domDoc->GetHidden(&hidden);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool mute = false;
|
||||
|
||||
nsRefPtr<AudioChannelService> audioChannelService = AudioChannelService::GetAudioChannelService();
|
||||
if (audioChannelService) {
|
||||
mute = audioChannelService->GetMuted(mAudioChannelType, hidden);
|
||||
}
|
||||
|
||||
// We have to mute this channel:
|
||||
if (mute && !mChannelMuted) {
|
||||
mChannelMuted = true;
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
|
||||
} else if (!mute && mChannelMuted) {
|
||||
mChannelMuted = false;
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
|
||||
}
|
||||
|
||||
SetMutedInternal(mMuted);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::UpdateAudioChannelPlayingState()
|
||||
{
|
||||
// The nsHTMLMediaElement is registered to the AudioChannelService only on B2G.
|
||||
#ifdef MOZ_B2G
|
||||
bool playingThroughTheAudioChannel =
|
||||
(mReadyState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA &&
|
||||
IsPotentiallyPlaying());
|
||||
if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
|
||||
mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
|
||||
|
||||
nsRefPtr<AudioChannelService> audioChannelService = AudioChannelService::GetAudioChannelService();
|
||||
if (!audioChannelService) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPlayingThroughTheAudioChannel) {
|
||||
audioChannelService->RegisterMediaElement(this, mAudioChannelType);
|
||||
} else {
|
||||
audioChannelService->UnregisterMediaElement(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsHTMLMediaElement::NotifyAudioChannelStateChanged()
|
||||
{
|
||||
return UpdateChannelMuteState();
|
||||
}
|
||||
|
||||
|
|
|
@ -333,8 +333,10 @@ MOCHITEST_FILES = \
|
|||
test_htmlcollection.html \
|
||||
test_formelements.html \
|
||||
test_rowscollection.html \
|
||||
test_mozaudiochannel.html \
|
||||
$(NULL)
|
||||
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
browser_bug649778.js \
|
||||
file_bug649778.html \
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for mozaudiochannel</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<audio id="audio1" />
|
||||
<audio id="audio2" mozaudiochannel="foo" />
|
||||
<audio id="audio3" mozaudiochannel="content" />
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
var audio1 = document.getElementById("audio1");
|
||||
ok(audio1, "Audio Element exists");
|
||||
ok(audio1.mozAudioChannelType == "normal", "Default audio1 channel == 'normal'");
|
||||
try {
|
||||
audio1.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
ok(audio1.mozAudioChannelType == "normal", "Default audio1 channel == 'normal'");
|
||||
audio1.mozAudioChannelType = "alarm";
|
||||
ok(audio1.mozAudioChannelType == "alarm", "Default audio1 channel == 'alarm'");
|
||||
|
||||
var audio2 = document.getElementById("audio2");
|
||||
ok(audio2, "Audio Element exists");
|
||||
ok(audio2.mozAudioChannelType == "normal", "Default audio2 channel == 'normal'");
|
||||
try {
|
||||
audio2.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
ok(audio2.mozAudioChannelType == "normal", "Default audio2 channel == 'normal'");
|
||||
audio2.mozAudioChannelType = "alarm";
|
||||
ok(audio2.mozAudioChannelType == "alarm", "Default audio2 channel == 'alarm'");
|
||||
|
||||
var audio3 = document.getElementById("audio3");
|
||||
ok(audio3, "Audio Element exists");
|
||||
ok(audio3.mozAudioChannelType == "content", "Default audio3 channel == 'content'");
|
||||
try {
|
||||
audio3.mozAudioChannelType = "foo";
|
||||
} catch(e) {}
|
||||
ok(audio3.mozAudioChannelType == "normal", "audio3 channel == 'normal'");
|
||||
audio3.mozAudioChannelType = "alarm";
|
||||
ok(audio3.mozAudioChannelType == "alarm", "audio3 channel == 'alarm'");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -43,7 +43,7 @@ MOCHITEST_FILES = test_bug1682.html \
|
|||
test_viewport.html \
|
||||
test_documentAll.html \
|
||||
test_document-element-inserted.html \
|
||||
test_bug445004.html \
|
||||
$(filter disabled-temporarily--bug-559932, test_bug445004.html) \
|
||||
bug445004-inner.js \
|
||||
bug445004-outer-rel.html \
|
||||
bug445004-outer-abs.html \
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "MediaResource.h"
|
||||
#include "nsError.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include <cstdlib> // for std::abs(int/long)
|
||||
#include <cmath> // for std::abs(float/double)
|
||||
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -561,11 +563,11 @@ nsresult MediaDecoder::Seek(double aTime)
|
|||
NS_ENSURE_SUCCESS(res, NS_OK);
|
||||
res = seekable.Start(range + 1, &rightBound);
|
||||
NS_ENSURE_SUCCESS(res, NS_OK);
|
||||
double distanceLeft = NS_ABS(leftBound - aTime);
|
||||
double distanceRight = NS_ABS(rightBound - aTime);
|
||||
double distanceLeft = std::abs(leftBound - aTime);
|
||||
double distanceRight = std::abs(rightBound - aTime);
|
||||
if (distanceLeft == distanceRight) {
|
||||
distanceLeft = NS_ABS(leftBound - mCurrentTime);
|
||||
distanceRight = NS_ABS(rightBound - mCurrentTime);
|
||||
distanceLeft = std::abs(leftBound - mCurrentTime);
|
||||
distanceRight = std::abs(rightBound - mCurrentTime);
|
||||
}
|
||||
aTime = (distanceLeft < distanceRight) ? leftBound : rightBound;
|
||||
} else {
|
||||
|
|
|
@ -504,7 +504,7 @@ public:
|
|||
void SetMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
// Set a flag indicating whether seeking is supported
|
||||
virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
|
||||
virtual void SetTransportSeekable(bool aTransportSeekable) MOZ_FINAL MOZ_OVERRIDE;
|
||||
// Returns true if this media supports seeking. False for example for WebM
|
||||
// files without an index and chained ogg files.
|
||||
|
|
|
@ -175,6 +175,8 @@ static const char* GetOmxLibraryName()
|
|||
|
||||
#elif defined(ANDROID) && defined(MOZ_WIDGET_GONK)
|
||||
return "libomxplugin.so";
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1087,7 +1087,7 @@ nsSVGSVGElement::GetCurrentViewElement() const
|
|||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
Element *element = doc->GetElementById(*mCurrentViewID);
|
||||
if (element && element->Tag() == nsGkAtoms::view) {
|
||||
if (element && element->IsSVG(nsGkAtoms::view)) {
|
||||
return static_cast<nsSVGViewElement*>(element);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2505,11 +2505,9 @@ nsXULPrototypeScript::Set(JSScript* aObject)
|
|||
return;
|
||||
}
|
||||
|
||||
nsresult rv = nsContentUtils::HoldJSObjects(
|
||||
nsContentUtils::HoldJSObjects(
|
||||
this, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mScriptObject.mObject = aObject;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
|
||||
// For calculating max history entries and max cachable contentviewers
|
||||
#include "nspr.h"
|
||||
#include <math.h> // for log()
|
||||
#include <cstdlib> // for std::abs(int/long)
|
||||
#include <cmath> // for std::abs(float/double), and std::log(double)
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -310,7 +311,7 @@ nsSHistory::CalcMaxTotalViewers()
|
|||
// except that we divide the final memory calculation by 4, since
|
||||
// we assume each ContentViewer takes on average 4MB
|
||||
uint32_t viewers = 0;
|
||||
double x = log(kBytesD)/log(2.0) - 14;
|
||||
double x = std::log(kBytesD)/std::log(2.0) - 14;
|
||||
if (x > 0) {
|
||||
viewers = (uint32_t)(x * x - x + 2.001); // add .001 for rounding
|
||||
viewers /= 4;
|
||||
|
@ -1088,7 +1089,7 @@ nsSHistory::GloballyEvictContentViewers()
|
|||
TransactionAndDistance &container = shTransactions[j];
|
||||
if (container.mViewer == contentViewer) {
|
||||
container.mDistance = NS_MIN(container.mDistance,
|
||||
NS_ABS(i - shist->mIndex));
|
||||
std::abs(i - shist->mIndex));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1097,7 +1098,7 @@ nsSHistory::GloballyEvictContentViewers()
|
|||
// If we didn't find a TransactionAndDistance for this content viewer, make a new
|
||||
// one.
|
||||
if (!found) {
|
||||
TransactionAndDistance container(trans, NS_ABS(i - shist->mIndex));
|
||||
TransactionAndDistance container(trans, std::abs(i - shist->mIndex));
|
||||
shTransactions.AppendElement(container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,6 @@ MOCHITEST_CHROME_FILES = \
|
|||
bug449778_window.xul \
|
||||
test_bug449780.xul \
|
||||
bug449780_window.xul \
|
||||
test_bug454235.xul \
|
||||
bug454235-subframe.xul \
|
||||
test_bug456980.xul \
|
||||
test_bug662200.xul \
|
||||
|
@ -97,11 +96,16 @@ MOCHITEST_CHROME_FILES = \
|
|||
test_bug789773.xul \
|
||||
test_bug754029.xul \
|
||||
bug754029_window.xul \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES += \
|
||||
docshell_helpers.js \
|
||||
generic.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||
MOCHITEST_CHROME_FILES += \
|
||||
test_bug454235.xul \
|
||||
$(NULL)
|
||||
else
|
||||
$(filter disabled-temporarily--bug-684176, test_bug454235.xul)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -56,7 +56,6 @@ MOCHITEST_FILES += \
|
|||
endif
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
browser_bug343515.js \
|
||||
bug343515_pg1.html \
|
||||
bug343515_pg2.html \
|
||||
bug343515_pg3.html \
|
||||
|
@ -65,4 +64,12 @@ MOCHITEST_BROWSER_FILES = \
|
|||
bug343515_pg3_1_1.html \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(OS_ARCH),WINNT)
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_bug343515.js \
|
||||
$(NULL)
|
||||
else
|
||||
$(filter disabled-temporarily--bug-813242, browser_bug343515.js)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -184,6 +184,15 @@ this.AppsUtils = {
|
|||
return true;
|
||||
},
|
||||
|
||||
checkManifestContentType: function
|
||||
checkManifestContentType(installOrigin, webappOrigin, contentType) {
|
||||
if (installOrigin != webappOrigin &&
|
||||
contentType != "application/x-web-app-manifest+json") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines whether the manifest allows installs for the given origin.
|
||||
* @param object aManifest
|
||||
|
|
|
@ -14,6 +14,7 @@ Cu.import("resource://gre/modules/PermissionSettings.jsm");
|
|||
this.EXPORTED_SYMBOLS = ["PermissionsInstaller",
|
||||
"expandPermissions",
|
||||
"PermissionsTable",
|
||||
"appendAccessToPermName"
|
||||
];
|
||||
const UNKNOWN_ACTION = Ci.nsIPermissionManager.UNKNOWN_ACTION;
|
||||
const ALLOW_ACTION = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
|
@ -32,17 +33,6 @@ function debug(aMsg) {
|
|||
//dump("-*-*- PermissionsInstaller.jsm : " + aMsg + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts ['read', 'write'] to ['contacts-read', 'contacts-write'], etc...
|
||||
* @param string aPermName
|
||||
* @param Array aSuffixes
|
||||
* @returns Array
|
||||
**/
|
||||
function mapSuffixes(aPermName, aSuffixes)
|
||||
{
|
||||
return aSuffixes.map(function(suf) { return aPermName + "-" + suf; });
|
||||
}
|
||||
|
||||
// Permissions Matrix: https://docs.google.com/spreadsheet/ccc?key=0Akyz_Bqjgf5pdENVekxYRjBTX0dCXzItMnRyUU1RQ0E#gid=0
|
||||
// Also, keep in sync with https://mxr.mozilla.org/mozilla-central/source/extensions/cookie/Permission.txt
|
||||
|
||||
|
@ -154,7 +144,7 @@ this.PermissionsTable = { geolocation: {
|
|||
certified: ALLOW_ACTION
|
||||
},
|
||||
fmradio: {
|
||||
app: ALLOW_ACTION, // Matrix indicates '?'
|
||||
app: ALLOW_ACTION,
|
||||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
|
@ -238,17 +228,42 @@ this.PermissionsTable = { geolocation: {
|
|||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
audio: {
|
||||
app: DENY_ACTION,
|
||||
privileged: ALLOW_ACTION,
|
||||
certified: ALLOW_ACTION,
|
||||
channels: ["normal", "content", "notification",
|
||||
"alarm", "telephony", "ringer", "publicnotification"]
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Append access modes to the permission name as suffixes.
|
||||
* e.g. permission name 'contacts' with ['read', 'write'] =
|
||||
* ['contacts-read', contacts-write']
|
||||
* @param string aPermName
|
||||
* @param array aAccess
|
||||
* @returns array containing access-appended permission names.
|
||||
**/
|
||||
this.appendAccessToPermName = function appendAccessToPermName(aPermName, aAccess) {
|
||||
if (aAccess.length == 0) {
|
||||
return [aPermName];
|
||||
}
|
||||
return aAccess.map(function(aMode) {
|
||||
return aPermName + "-" + aMode;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand an access string into multiple permission names,
|
||||
* e.g: perm 'contacts' with 'readwrite' =
|
||||
* ['contacts-read', 'contacts-create', contacts-write']
|
||||
* e.g: permission name 'contacts' with 'readwrite' =
|
||||
* ['contacts-read', 'contacts-create', 'contacts-write']
|
||||
* @param string aPermName
|
||||
* @param string aAccess
|
||||
* @returns Array
|
||||
* @param string array aChannels
|
||||
* @returns array containing expanded permission names.
|
||||
**/
|
||||
this.expandPermissions = function expandPermissions(aPermName, aAccess) {
|
||||
this.expandPermissions = function expandPermissions(aPermName, aAccess, aChannels) {
|
||||
if (!PermissionsTable[aPermName]) {
|
||||
Cu.reportError("PermissionsTable.jsm: expandPermissions: Unknown Permission: " + aPermName);
|
||||
dump("PermissionsTable.jsm: expandPermissions: Unknown Permission: " + aPermName);
|
||||
|
@ -273,7 +288,7 @@ this.expandPermissions = function expandPermissions(aPermName, aAccess) {
|
|||
aPermName + " " + aAccess + "\n");
|
||||
}
|
||||
|
||||
let expandedPerms = [];
|
||||
let expandedPermNames = [];
|
||||
|
||||
if (tableEntry.access && aAccess) {
|
||||
let requestedSuffixes = [];
|
||||
|
@ -294,12 +309,12 @@ this.expandPermissions = function expandPermissions(aPermName, aAccess) {
|
|||
return [];
|
||||
}
|
||||
|
||||
let permArr = mapSuffixes(aPermName, requestedSuffixes);
|
||||
let permArr = appendAccessToPermName(aPermName, requestedSuffixes);
|
||||
|
||||
// Add the same suffix to each of the additions.
|
||||
if (tableEntry.additional) {
|
||||
for each (let additional in tableEntry.additional) {
|
||||
permArr = permArr.concat(mapSuffixes(additional, requestedSuffixes));
|
||||
permArr = permArr.concat(appendAccessToPermName(additional, requestedSuffixes));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,28 +322,43 @@ this.expandPermissions = function expandPermissions(aPermName, aAccess) {
|
|||
for (let idx in permArr) {
|
||||
let suffix = requestedSuffixes[idx % requestedSuffixes.length];
|
||||
if (tableEntry.access.indexOf(suffix) != -1) {
|
||||
expandedPerms.push(permArr[idx]);
|
||||
expandedPermNames.push(permArr[idx]);
|
||||
}
|
||||
}
|
||||
} else if (tableEntry.substitute) {
|
||||
expandedPerms = expandedPerms.concat(tableEntry.substitute);
|
||||
expandedPermNames = expandedPermNames.concat(tableEntry.substitute);
|
||||
} else if (tableEntry.channels) {
|
||||
if ("audio" == aPermName && aChannels) {
|
||||
let allowChannels = tableEntry.channels;
|
||||
|
||||
for (let idx in aChannels) {
|
||||
let candidate = aChannels[idx];
|
||||
if (allowChannels.indexOf(candidate) == -1) {
|
||||
continue;
|
||||
}
|
||||
let permAttr = aPermName + "-channel-" + candidate;
|
||||
expandedPermNames.push(permAttr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expandedPerms.push(aPermName);
|
||||
expandedPermNames.push(aPermName);
|
||||
// Include each of the additions exactly as they appear in the table.
|
||||
if (tableEntry.additional) {
|
||||
expandedPerms = expandedPerms.concat(tableEntry.additional);
|
||||
expandedPermNames = expandedPermNames.concat(tableEntry.additional);
|
||||
}
|
||||
}
|
||||
|
||||
return expandedPerms;
|
||||
return expandedPermNames;
|
||||
};
|
||||
|
||||
// Sometimes all permissions (fully expanded) need to be iterated through
|
||||
// An array carring all the possible (expanded) permission names.
|
||||
let AllPossiblePermissions = [];
|
||||
for (let permName in PermissionsTable) {
|
||||
if (PermissionsTable[permName].access) {
|
||||
AllPossiblePermissions =
|
||||
AllPossiblePermissions.concat(expandPermissions(permName, READWRITE));
|
||||
} else if (PermissionsTable[permName].channels) {
|
||||
AllPossiblePermissions.concat(expandPermissions(permName, null, PermissionsTable[permName].channels));
|
||||
} else {
|
||||
AllPossiblePermissions =
|
||||
AllPossiblePermissions.concat(expandPermissions(permName));
|
||||
|
@ -336,11 +366,11 @@ for (let permName in PermissionsTable) {
|
|||
}
|
||||
|
||||
this.PermissionsInstaller = {
|
||||
/**
|
||||
* Install permissisions or remove deprecated permissions upon re-install
|
||||
/**
|
||||
* Install permissisions or remove deprecated permissions upon re-install.
|
||||
* @param object aApp
|
||||
* The just-installed app configuration.
|
||||
The properties used are manifestURL, origin and manifest.
|
||||
* The properties used are manifestURL, origin and manifest.
|
||||
* @param boolean aIsReinstall
|
||||
* Indicates the app was just re-installed
|
||||
* @param function aOnError
|
||||
|
@ -359,66 +389,74 @@ this.PermissionsInstaller = {
|
|||
// Remove any deprecated Permissions
|
||||
|
||||
if (newManifest.permissions) {
|
||||
// Expand perms
|
||||
let newPerms = [];
|
||||
for (let perm in newManifest.permissions) {
|
||||
let _perms = expandPermissions(perm,
|
||||
newManifest.permissions[perm].access);
|
||||
newPerms = newPerms.concat(_perms);
|
||||
// Expand permission names.
|
||||
let newPermNames = [];
|
||||
for (let permName in newManifest.permissions) {
|
||||
let expandedPermNames =
|
||||
expandPermissions(permName,
|
||||
newManifest.permissions[permName].access,
|
||||
newManifest.permissions[permName].channels);
|
||||
newPermNames = newPermNames.concat(expandedPermNames);
|
||||
}
|
||||
|
||||
for (let idx in AllPossiblePermissions) {
|
||||
let index = newPerms.indexOf(AllPossiblePermissions[idx]);
|
||||
let permName = AllPossiblePermissions[idx];
|
||||
let index = newPermNames.indexOf(permName);
|
||||
if (index == -1) {
|
||||
// See if the permission was installed previously
|
||||
let _perm = PermissionSettingsModule.getPermission(AllPossiblePermissions[idx],
|
||||
// See if the permission was installed previously.
|
||||
let permValue =
|
||||
PermissionSettingsModule.getPermission(permName,
|
||||
aApp.manifestURL,
|
||||
aApp.origin,
|
||||
false);
|
||||
if (_perm == "unknown" || _perm == "deny") {
|
||||
if (permValue == "unknown" || permValue == "deny") {
|
||||
// All 'deny' permissions should be preserved
|
||||
continue;
|
||||
}
|
||||
// Remove the deprecated permission
|
||||
// TODO: use PermSettings.remove, see bug 793204
|
||||
this._setPermission(AllPossiblePermissions[idx], "unknown", aApp);
|
||||
this._setPermission(permName, "unknown", aApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let installPermType;
|
||||
// Check to see if the 'webapp' is app/priv/certified
|
||||
// Check to see if the 'webapp' is app/privileged/certified.
|
||||
let appStatus;
|
||||
switch (AppsUtils.getAppManifestStatus(aApp.manifest)) {
|
||||
case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
|
||||
installPermType = "certified";
|
||||
appStatus = "certified";
|
||||
break;
|
||||
case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED:
|
||||
installPermType = "privileged";
|
||||
appStatus = "privileged";
|
||||
break;
|
||||
case Ci.nsIPrincipal.APP_STATUS_INSTALLED:
|
||||
installPermType = "app";
|
||||
appStatus = "app";
|
||||
break;
|
||||
default:
|
||||
// Cannot determine app type, abort install by throwing an error
|
||||
throw new Error("PermissionsInstaller.jsm: Cannot determine app type, install cancelled");
|
||||
// Cannot determine app type, abort install by throwing an error.
|
||||
throw new Error("PermissionsInstaller.jsm: " +
|
||||
"Cannot determine the app's status. Install cancelled.");
|
||||
break;
|
||||
}
|
||||
|
||||
for (let permName in newManifest.permissions) {
|
||||
if (!PermissionsTable[permName]) {
|
||||
Cu.reportError("PermissionsInstaller.jsm: '" + permName + "'" +
|
||||
" is not a valid Webapps permission type.");
|
||||
" is not a valid Webapps permission name.");
|
||||
dump("PermissionsInstaller.jsm: '" + permName + "'" +
|
||||
" is not a valid Webapps permission type.");
|
||||
" is not a valid Webapps permission name.");
|
||||
continue;
|
||||
}
|
||||
|
||||
let perms = expandPermissions(permName,
|
||||
newManifest.permissions[permName].access);
|
||||
for (let idx in perms) {
|
||||
let perm = PermissionsTable[permName][installPermType];
|
||||
let permValue = PERM_TO_STRING[perm];
|
||||
this._setPermission(perms[idx], permValue, aApp);
|
||||
let expandedPermNames =
|
||||
expandPermissions(permName,
|
||||
newManifest.permissions[permName].access,
|
||||
newManifest.permissions[permName].channels);
|
||||
for (let idx in expandedPermNames) {
|
||||
this._setPermission(expandedPermNames[idx],
|
||||
PERM_TO_STRING[PermissionsTable[permName][appStatus]],
|
||||
aApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,22 +470,22 @@ this.PermissionsInstaller = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Set a permission value
|
||||
* @param string aPerm
|
||||
* Set a permission value.
|
||||
* @param string aPermName
|
||||
* The permission name.
|
||||
* @param string aValue
|
||||
* @param string aPermValue
|
||||
* The permission value.
|
||||
* @param object aApp
|
||||
* The just-installed app configuration.
|
||||
The properties used are manifestURL, origin and manifest.
|
||||
* The properties used are manifestURL and origin.
|
||||
* @returns void
|
||||
**/
|
||||
_setPermission: function setPermission(aPerm, aValue, aApp) {
|
||||
_setPermission: function setPermission(aPermName, aPermValue, aApp) {
|
||||
PermissionSettingsModule.addPermission({
|
||||
type: aPerm,
|
||||
type: aPermName,
|
||||
origin: aApp.origin,
|
||||
manifestURL: aApp.manifestURL,
|
||||
value: aValue,
|
||||
value: aPermValue,
|
||||
browserFlag: false
|
||||
});
|
||||
}
|
||||
|
|
|
@ -105,6 +105,12 @@ WebappsRegistry.prototype = {
|
|||
|
||||
xhr.addEventListener("load", (function() {
|
||||
if (xhr.status == 200) {
|
||||
if (!AppsUtils.checkManifestContentType(installOrigin, this._getOrigin(aURL),
|
||||
xhr.getResponseHeader("content-type"))) {
|
||||
Services.DOMRequest.fireError(request, "INVALID_MANIFEST");
|
||||
return;
|
||||
}
|
||||
|
||||
let manifest;
|
||||
try {
|
||||
manifest = JSON.parse(xhr.responseText, installOrigin);
|
||||
|
@ -214,6 +220,12 @@ WebappsRegistry.prototype = {
|
|||
|
||||
xhr.addEventListener("load", (function() {
|
||||
if (xhr.status == 200) {
|
||||
if (!AppsUtils.checkManifestContentType(installOrigin, this._getOrigin(aURL),
|
||||
xhr.getResponseHeader("content-type"))) {
|
||||
Services.DOMRequest.fireError(request, "INVALID_MANIFEST");
|
||||
return;
|
||||
}
|
||||
|
||||
let manifest;
|
||||
try {
|
||||
manifest = JSON.parse(xhr.responseText, installOrigin);
|
||||
|
|
|
@ -18,6 +18,7 @@ Cu.import('resource://gre/modules/ActivitiesService.jsm');
|
|||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
|
||||
Cu.import("resource://gre/modules/OfflineCacheInstaller.jsm");
|
||||
Cu.import("resource://gre/modules/SystemMessagePermissionsChecker.jsm");
|
||||
|
||||
function debug(aMsg) {
|
||||
//dump("-*-*- Webapps.jsm : " + aMsg + "\n");
|
||||
|
@ -43,6 +44,11 @@ XPCOMUtils.defineLazyGetter(this, "msgmgr", function() {
|
|||
.getService(Ci.nsISystemMessagesInternal);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "updateSvc", function() {
|
||||
return Cc["@mozilla.org/offlinecacheupdate-service;1"]
|
||||
.getService(Ci.nsIOfflineCacheUpdateService);
|
||||
});
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
const DIRECTORY_NAME = "webappsDir";
|
||||
#elifdef ANDROID
|
||||
|
@ -333,7 +339,13 @@ this.DOMApplicationRegistry = {
|
|||
} else {
|
||||
messageName = aMessage;
|
||||
}
|
||||
|
||||
if (SystemMessagePermissionsChecker
|
||||
.isSystemMessagePermittedToRegister(messageName,
|
||||
aApp.origin,
|
||||
aManifest)) {
|
||||
msgmgr.registerPage(messageName, href, manifestURL);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -380,8 +392,14 @@ this.DOMApplicationRegistry = {
|
|||
|
||||
let launchPath = Services.io.newURI(description.href, null, null);
|
||||
let manifestURL = Services.io.newURI(aApp.manifestURL, null, null);
|
||||
|
||||
if (SystemMessagePermissionsChecker
|
||||
.isSystemMessagePermittedToRegister("activity",
|
||||
aApp.origin,
|
||||
aManifest)) {
|
||||
msgmgr.registerPage("activity", launchPath, manifestURL);
|
||||
}
|
||||
}
|
||||
return activitiesToRegister;
|
||||
},
|
||||
|
||||
|
@ -918,8 +936,6 @@ this.DOMApplicationRegistry = {
|
|||
// if the manifest has an appcache_path property, use it to populate the appcache
|
||||
if (aManifest.appcache_path) {
|
||||
let appcacheURI = Services.io.newURI(aManifest.fullAppcachePath(), null, null);
|
||||
let updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"]
|
||||
.getService(Ci.nsIOfflineCacheUpdateService);
|
||||
let docURI = Services.io.newURI(aManifest.fullLaunchPath(), null, null);
|
||||
// We determine the app's 'installState' according to its previous
|
||||
// state. Cancelled download should remain as 'pending'. Successfully
|
||||
|
@ -930,8 +946,9 @@ this.DOMApplicationRegistry = {
|
|||
// We set the 'downloading' flag right before starting the app
|
||||
// download/update.
|
||||
aApp.downloading = true;
|
||||
let cacheUpdate = aProfileDir ? updateService.scheduleCustomProfileUpdate(appcacheURI, docURI, aProfileDir)
|
||||
: updateService.scheduleAppUpdate(appcacheURI, docURI, aApp.localId, false);
|
||||
let cacheUpdate = aProfileDir
|
||||
? updateSvc.scheduleCustomProfileUpdate(appcacheURI, docURI, aProfileDir)
|
||||
: updateSvc.scheduleAppUpdate(appcacheURI, docURI, aApp.localId, false);
|
||||
cacheUpdate.addObserver(new AppcacheObserver(aApp), false);
|
||||
if (aOfflineCacheObserver) {
|
||||
cacheUpdate.addObserver(aOfflineCacheObserver, false);
|
||||
|
@ -984,6 +1001,7 @@ this.DOMApplicationRegistry = {
|
|||
debug("updateHostedApp " + aData.manifestURL);
|
||||
let id = this._appId(app.origin);
|
||||
|
||||
// Clean up the deprecated manifest cache if needed.
|
||||
if (id in this._manifestCache) {
|
||||
delete this._manifestCache[id];
|
||||
}
|
||||
|
@ -1024,9 +1042,23 @@ this.DOMApplicationRegistry = {
|
|||
|
||||
this._saveApps(function() {
|
||||
aData.app = app;
|
||||
aData.event = manifest.appcache_path ? "downloadavailable"
|
||||
if (!manifest.appcache_path) {
|
||||
aData.event = "downloadapplied";
|
||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:OK", aData);
|
||||
} else {
|
||||
// Check if the appcache is updatable, and send "downloadavailable" or
|
||||
// "downloadapplied".
|
||||
let updateObserver = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
aData.event =
|
||||
aTopic == "offline-cache-update-available" ? "downloadavailable"
|
||||
: "downloadapplied";
|
||||
aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:OK", aData);
|
||||
}
|
||||
}
|
||||
updateSvc.checkForUpdate(Services.io.newURI(aData.manifestURL, null, null),
|
||||
app.localId, false, updateObserver);
|
||||
}
|
||||
});
|
||||
|
||||
// Update the permissions for this app.
|
||||
|
|
|
@ -18,7 +18,8 @@ enum AudioChannelType {
|
|||
AUDIO_CHANNEL_NOTIFICATION,
|
||||
AUDIO_CHANNEL_ALARM,
|
||||
AUDIO_CHANNEL_TELEPHONY,
|
||||
AUDIO_CHANNEL_PUBLICNOTIFICATION
|
||||
AUDIO_CHANNEL_PUBLICNOTIFICATION,
|
||||
AUDIO_CHANNEL_LAST
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AudioChannelService.h"
|
||||
#include "AudioChannelServiceChild.h"
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
StaticRefPtr<AudioChannelService> gAudioChannelService;
|
||||
|
||||
// static
|
||||
AudioChannelService*
|
||||
AudioChannelService::GetAudioChannelService()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
return AudioChannelServiceChild::GetAudioChannelService();
|
||||
}
|
||||
|
||||
// If we already exist, exit early
|
||||
if (gAudioChannelService) {
|
||||
return gAudioChannelService;
|
||||
}
|
||||
|
||||
// Create new instance, register, return
|
||||
nsRefPtr<AudioChannelService> service = new AudioChannelService();
|
||||
NS_ENSURE_TRUE(service, nullptr);
|
||||
|
||||
gAudioChannelService = service;
|
||||
return gAudioChannelService;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::Shutdown()
|
||||
{
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
return AudioChannelServiceChild::Shutdown();
|
||||
}
|
||||
|
||||
if (gAudioChannelService) {
|
||||
delete gAudioChannelService;
|
||||
gAudioChannelService = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS0(AudioChannelService)
|
||||
|
||||
AudioChannelService::AudioChannelService()
|
||||
: mCurrentHigherChannel(AUDIO_CHANNEL_NORMAL)
|
||||
{
|
||||
mChannelCounters = new int32_t[AUDIO_CHANNEL_PUBLICNOTIFICATION+1];
|
||||
|
||||
for (int i = AUDIO_CHANNEL_NORMAL;
|
||||
i <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
++i) {
|
||||
mChannelCounters[i] = 0;
|
||||
}
|
||||
|
||||
// Creation of the hash table.
|
||||
mMediaElements.Init();
|
||||
}
|
||||
|
||||
AudioChannelService::~AudioChannelService()
|
||||
{
|
||||
delete [] mChannelCounters;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
|
||||
AudioChannelType aType)
|
||||
{
|
||||
mMediaElements.Put(aMediaElement, aType);
|
||||
RegisterType(aType);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RegisterType(AudioChannelType aType)
|
||||
{
|
||||
mChannelCounters[aType]++;
|
||||
|
||||
// In order to avoid race conditions, it's safer to notify any existing
|
||||
// media element any time a new one is registered.
|
||||
Notify();
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::UnregisterMediaElement(nsHTMLMediaElement* aMediaElement)
|
||||
{
|
||||
AudioChannelType type;
|
||||
if (!mMediaElements.Get(aMediaElement, &type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mMediaElements.Remove(aMediaElement);
|
||||
UnregisterType(type);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::UnregisterType(AudioChannelType aType)
|
||||
{
|
||||
mChannelCounters[aType]--;
|
||||
MOZ_ASSERT(mChannelCounters[aType] >= 0);
|
||||
|
||||
// In order to avoid race conditions, it's safer to notify any existing
|
||||
// media element any time a new one is registered.
|
||||
Notify();
|
||||
}
|
||||
|
||||
bool
|
||||
AudioChannelService::GetMuted(AudioChannelType aType, bool aElementHidden)
|
||||
{
|
||||
// We are not visible, maybe we have to mute:
|
||||
if (aElementHidden) {
|
||||
switch (aType) {
|
||||
case AUDIO_CHANNEL_NORMAL:
|
||||
return true;
|
||||
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
// TODO: this should work per apps
|
||||
if (mChannelCounters[AUDIO_CHANNEL_CONTENT] > 1)
|
||||
return true;
|
||||
break;
|
||||
|
||||
case AUDIO_CHANNEL_NOTIFICATION:
|
||||
case AUDIO_CHANNEL_ALARM:
|
||||
case AUDIO_CHANNEL_TELEPHONY:
|
||||
case AUDIO_CHANNEL_PUBLICNOTIFICATION:
|
||||
// Nothing to do
|
||||
break;
|
||||
|
||||
case AUDIO_CHANNEL_LAST:
|
||||
MOZ_NOT_REACHED();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool muted = false;
|
||||
|
||||
// Priorities:
|
||||
switch (aType) {
|
||||
case AUDIO_CHANNEL_NORMAL:
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
muted = !!mChannelCounters[AUDIO_CHANNEL_NOTIFICATION] ||
|
||||
!!mChannelCounters[AUDIO_CHANNEL_ALARM] ||
|
||||
!!mChannelCounters[AUDIO_CHANNEL_TELEPHONY] ||
|
||||
!!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION];
|
||||
|
||||
case AUDIO_CHANNEL_NOTIFICATION:
|
||||
case AUDIO_CHANNEL_ALARM:
|
||||
case AUDIO_CHANNEL_TELEPHONY:
|
||||
muted = ChannelsActiveWithHigherPriorityThan(aType);
|
||||
|
||||
case AUDIO_CHANNEL_PUBLICNOTIFICATION:
|
||||
break;
|
||||
|
||||
case AUDIO_CHANNEL_LAST:
|
||||
MOZ_NOT_REACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Notification if needed.
|
||||
if (!muted) {
|
||||
|
||||
// Calculating the most important unmuted channel:
|
||||
AudioChannelType higher = AUDIO_CHANNEL_NORMAL;
|
||||
for (int32_t type = AUDIO_CHANNEL_NORMAL;
|
||||
type <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
++type) {
|
||||
if (mChannelCounters[type]) {
|
||||
higher = (AudioChannelType)type;
|
||||
}
|
||||
}
|
||||
|
||||
if (higher != mCurrentHigherChannel) {
|
||||
mCurrentHigherChannel = higher;
|
||||
|
||||
nsString channelName;
|
||||
channelName.AssignASCII(ChannelName(mCurrentHigherChannel));
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(nullptr, "audio-channel-changed", channelName.get());
|
||||
}
|
||||
}
|
||||
|
||||
return muted;
|
||||
}
|
||||
|
||||
|
||||
static PLDHashOperator
|
||||
NotifyEnumerator(nsHTMLMediaElement* aElement,
|
||||
AudioChannelType aType, void* aData)
|
||||
{
|
||||
if (aElement) {
|
||||
aElement->NotifyAudioChannelStateChanged();
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::Notify()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Notify any media element for the main process.
|
||||
mMediaElements.EnumerateRead(NotifyEnumerator, nullptr);
|
||||
|
||||
// Notify for the child processes.
|
||||
nsTArray<ContentParent*> children;
|
||||
ContentParent::GetAll(children);
|
||||
for (uint32_t i = 0; i < children.Length(); i++) {
|
||||
unused << children[i]->SendAudioChannelNotify();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AudioChannelService::ChannelsActiveWithHigherPriorityThan(AudioChannelType aType)
|
||||
{
|
||||
for (int i = AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
i != AUDIO_CHANNEL_CONTENT; --i) {
|
||||
if (i == aType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mChannelCounters[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char*
|
||||
AudioChannelService::ChannelName(AudioChannelType aType)
|
||||
{
|
||||
static struct {
|
||||
int32_t type;
|
||||
const char* value;
|
||||
} ChannelNameTable[] = {
|
||||
{ AUDIO_CHANNEL_NORMAL, "normal" },
|
||||
{ AUDIO_CHANNEL_CONTENT, "normal" },
|
||||
{ AUDIO_CHANNEL_NOTIFICATION, "notification" },
|
||||
{ AUDIO_CHANNEL_ALARM, "alarm" },
|
||||
{ AUDIO_CHANNEL_TELEPHONY, "telephony" },
|
||||
{ AUDIO_CHANNEL_PUBLICNOTIFICATION, "publicnotification" },
|
||||
{ -1, "unknown" }
|
||||
};
|
||||
|
||||
for (int i = AUDIO_CHANNEL_NORMAL; ; ++i) {
|
||||
if (ChannelNameTable[i].type == aType ||
|
||||
ChannelNameTable[i].type == -1) {
|
||||
return ChannelNameTable[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Execution should not reach here!");
|
||||
return nullptr;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_audiochannelservice_h__
|
||||
#define mozilla_dom_audiochannelservice_h__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
#include "AudioChannelCommon.h"
|
||||
#include "nsHTMLMediaElement.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioChannelService : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
/**
|
||||
* Returns the AudioChannelServce singleton. Only to be called from main thread.
|
||||
* @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise.
|
||||
*/
|
||||
static AudioChannelService*
|
||||
GetAudioChannelService();
|
||||
|
||||
/**
|
||||
* Shutdown the singleton.
|
||||
*/
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
* Any MediaElement that starts playing should register itself to
|
||||
* this service, sharing the AudioChannelType.
|
||||
*/
|
||||
virtual void RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
|
||||
AudioChannelType aType);
|
||||
|
||||
/**
|
||||
* Any MediaElement that stops playing should unregister itself to
|
||||
* this service.
|
||||
*/
|
||||
virtual void UnregisterMediaElement(nsHTMLMediaElement* aMediaElement);
|
||||
|
||||
/**
|
||||
* Return true if this type should be muted.
|
||||
*/
|
||||
virtual bool GetMuted(AudioChannelType aType, bool aElementHidden);
|
||||
|
||||
protected:
|
||||
void Notify();
|
||||
|
||||
/* Register/Unregister IPC types: */
|
||||
void RegisterType(AudioChannelType aType);
|
||||
void UnregisterType(AudioChannelType aType);
|
||||
|
||||
AudioChannelService();
|
||||
virtual ~AudioChannelService();
|
||||
|
||||
bool ChannelsActiveWithHigherPriorityThan(AudioChannelType aType);
|
||||
|
||||
const char* ChannelName(AudioChannelType aType);
|
||||
|
||||
nsDataHashtable< nsPtrHashKey<nsHTMLMediaElement>, AudioChannelType > mMediaElements;
|
||||
|
||||
int32_t* mChannelCounters;
|
||||
|
||||
AudioChannelType mCurrentHigherChannel;
|
||||
|
||||
// This is needed for IPC comunication between
|
||||
// AudioChannelServiceChild and this class.
|
||||
friend class ContentParent;
|
||||
friend class ContentChild;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -0,0 +1,103 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AudioChannelServiceChild.h"
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
StaticRefPtr<AudioChannelServiceChild> gAudioChannelServiceChild;
|
||||
|
||||
// static
|
||||
AudioChannelService*
|
||||
AudioChannelServiceChild::GetAudioChannelService()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If we already exist, exit early
|
||||
if (gAudioChannelServiceChild) {
|
||||
return gAudioChannelServiceChild;
|
||||
}
|
||||
|
||||
// Create new instance, register, return
|
||||
nsRefPtr<AudioChannelServiceChild> service = new AudioChannelServiceChild();
|
||||
NS_ENSURE_TRUE(service, nullptr);
|
||||
|
||||
gAudioChannelServiceChild = service;
|
||||
return gAudioChannelServiceChild;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelServiceChild::Shutdown()
|
||||
{
|
||||
if (gAudioChannelServiceChild) {
|
||||
delete gAudioChannelServiceChild;
|
||||
gAudioChannelServiceChild = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AudioChannelServiceChild::AudioChannelServiceChild()
|
||||
{
|
||||
}
|
||||
|
||||
AudioChannelServiceChild::~AudioChannelServiceChild()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
AudioChannelServiceChild::GetMuted(AudioChannelType aType, bool aMozHidden)
|
||||
{
|
||||
ContentChild *cc = ContentChild::GetSingleton();
|
||||
bool muted = false;
|
||||
|
||||
if (cc) {
|
||||
cc->SendAudioChannelGetMuted(aType, aMozHidden, &muted);
|
||||
}
|
||||
|
||||
return muted;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelServiceChild::RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
|
||||
AudioChannelType aType)
|
||||
{
|
||||
AudioChannelService::RegisterMediaElement(aMediaElement, aType);
|
||||
|
||||
ContentChild *cc = ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
cc->SendAudioChannelRegisterType(aType);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelServiceChild::UnregisterMediaElement(nsHTMLMediaElement* aMediaElement)
|
||||
{
|
||||
AudioChannelType type;
|
||||
if (!mMediaElements.Get(aMediaElement, &type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AudioChannelService::UnregisterMediaElement(aMediaElement);
|
||||
|
||||
ContentChild *cc = ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
cc->SendAudioChannelUnregisterType(type);
|
||||
}
|
||||
}
|
||||
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче