This commit is contained in:
Richard Newman 2012-12-05 23:59:56 -08:00
Родитель df3d814ae8 eec5c26676
Коммит 80a3f4f3ee
587 изменённых файлов: 12899 добавлений и 6372 удалений

Просмотреть файл

@ -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; &gt; &privateBrowsingCmd.stop.label;, or close &brandShortName;.">
<!ENTITY privatebrowsingpage.howToStart2 "To start Private Browsing, you can also select &basePBMenu.label; &gt; &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; &gt; &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"
##############################################

Просмотреть файл

@ -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, "&gt;").replace(/</g, "&lt;");
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,12 +2505,10 @@ 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));
@ -337,10 +367,10 @@ 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);
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше