Полезная информация

Заказывай стафф с атрибутикой Mozilla и... пусть все вокруг завидуют тебе! Быть уникальным - быть с Mozilla!

№129-01-2024 19:18:12

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1090
UA: Seamonkey 2.49

Закрыть окошки дополнения

Здравствуйте.


Вопрос у меня на связан напрямую с CB, но задать его больше негде.


После многих лет занятия чем попало попытался немного вернуться к браузероковырянию и усовершенствовать одно из своих любимых и давно используемых дополнений.


Когда вся основная работа была сделана и желаемый результат достигнут, решил ещё для красоты приделать "сбоку бантик", и в результате получил такое "чёрти-что", что не знаю, что и подумать.


Суть проблемы:


Дополнение при вызове открывает своё окно. Оно не модальное, висит себе рядом с браузером, работать не мешает.


Из этого окна можно открыть диалог. Из этого диалога можно открыть второй диалог, из которого в тяжёлых случаях может быть открыть ещё и третий диалог.


Вся эта конструкция живёт своей жизнью и остаётся на экране, даже когда все окна браузера уже закрыты.


В принципе, меня это всю жизнь устраивало, но сейчас решил добавить в настройки галочку "Закрывать при выходе из браузера". Для этого добавил в существующий код XPCOM-component, который отслеживает приход сообщения "browser-lastwindow-close-granted", по получению которого закрывает все имеющиеся окна дополнения. Опознаёт "свои" окна он по их типу.


Код закрытия простой:

Выделить код

Код:

var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                   .getService(Components.interfaces.nsIWindowMediator);

var we = wm.getEnumerator("my_addon_window");
var wa = [];

while (we.hasMoreElements()) {
  wa.push(we.getNext());
}

while (wa.length > 0) {
  we = wa.pop();
  we.close();
}

(Извращение с массивом нужно, чтобы закрывать окна в порядке, обратном их открытию, т.к. все диалоги модальные.)


И вот тут обнаружилось, что сколько бы у моего дополнения ни было открыто окон, закрывается только самое последнее (верхнее) из них. Все остальные вызов close() просто игнорируют и остаются существовать (а браузер закрывается, как это и было в "прежней жизни").


Более того, если после исполнения данного кода запустить его ещё раз, то ни одно из оставшихся окон так и не закроется. При этом окошки в этой ситуации не зависшие, своё основное дело делают и мышкой потом совершенно нормально закрываются.


Почему так происходит и как же их программно все позакрывать?

Отредактировано yup (29-01-2024 19:23:18)

Отсутствует

 

№229-01-2024 20:46:47

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 78.0

Re: Закрыть окошки дополнения

yup пишет

одно из своих любимых и давно используемых дополнений

https://www.upload.ee/

Отсутствует

 

№329-01-2024 22:47:28

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 78.0

Re: Закрыть окошки дополнения

Хмм, попробовал воспроизвести вслепую.
Понаоткрывал кодом alert'ов, первый с окна браузера,
второй с окна первого alert'а, третий со второго, и так далее.
Проставил по пути атрибут "windowtype", все дела...


И действительно, пытаюсь закрыть alert'ы предоставленным кодом,
но закрывается только последний открытый.


Но если закрывать с некоторой задержкой, тогда нормально.
То есть, вместо

Выделить код

Код:

while (wa.length > 0) {
  we = wa.pop();
  we.close();
}

что-то типа

Выделить код

Код:

if (wa.length > 1) {
  var timer = Components.classes["@mozilla.org/timer;1"]
    .createInstance(Components.interfaces.nsITimer);
  var close = function() {
    wa.pop().close();
    wa.length && timer.initWithCallback(close, 100, timer.TYPE_ONE_SHOT);
  }
  close();
}
else if (wa.length == 1) wa[0].close();

Если работает — аддон не требуется.

Отсутствует

 

№430-01-2024 00:42:56

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1090
UA: Seamonkey 2.49

Re: Закрыть окошки дополнения

Dumby пишет

Если работает — аддон не требуется.

А я как раз соорудил минималистичный вариант, в котором ничего постороннего.


Dumby пишет

Но если закрывать с некоторой задержкой, тогда нормально.

Ох, было у меня такое подозрение, что причина именно в том, что потомок не успевает закрыться до вызова close() у родителя, но попробовал несколько раз подряд руками запускать ту свою закрывающую функцию из консоли браузера и получил описанную ранее картину: при первом запуске закрывается верхнее окно, при последующих уже ничего дополнительно не закрывается. Из этого радостно сделал вывод, что причина в чём-то другом.


Dumby пишет

Если работает

Работать-то работает, но слово "радостно" я употребил потому, что это на мини-примере всё хорошо и прекрасно, а в реальной жизни в этих окошках находятся данные, их может быть много и они ещё не сохранены. При закрывании окошка начинается их запись на диск, длительность которой предугадать невозможно (особенно если процессор чем-то другим под 100% загружен), и поэтому ни на какое разумное число миллисекунд полагаться нельзя.


Кроме того, таймеры- это асинхронность, а у нас происходит закрытие браузера, и есть ненулевая вероятность, что его внутренние службы остановятся раньше, чем последние данные на запись отправятся - это ведь уже этап "close-granted". И тут даже переход на чуть более ранний этап - "close-requested" - по большому счёту, не спасает. Разве что тормознуть завершение и написать пользователю: "Закрывай окошки руками". Но тогда смысл затеи пропадает - руками пользователь и при прежнем "образе жизни" закрывал, причём тогда, когда хотел.


Сейчас попробую с Promise поиграться.


Хотя, наверное, по поводу остановки служб я зря нервничаю, ведь, по идее, они не должны отключаться, пока последнее окно (не браузера, а вообще) не закроется.

Отредактировано yup (30-01-2024 00:53:32)

Отсутствует

 

№530-01-2024 11:13:33

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2249
UA: Firefox 78.0

Re: Закрыть окошки дополнения

Кстати, у меня и в цикле while работает, если перед we.close();
вызвать nsIDOMWindowUtils.leaveModalState(), типа


wa.length && wa.pop().close();


while (wa.length > 0) {
  we = wa.pop();


  we.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
    .getInterface(Components.interfaces.nsIDOMWindowUtils).leaveModalState();


  we.close();
}

Отсутствует

 

№630-01-2024 12:24:54

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1090
UA: Seamonkey 2.49

Re: Закрыть окошки дополнения

Великолепно! Я о существовании leaveModalState() даже не подозревал.


Спасибо огромное.

Отсутствует

 

№730-01-2024 18:42:29

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1090
UA: Seamonkey 2.49

Re: Закрыть окошки дополнения

Подчищал-удалял разные свои записи, сделанные во время этой работы, и нашёл там вот какое наблюдение.


Запускаем браузер, открываем Консоль браузера, закрываем окно браузера. Оказывается, то, что при этом происходит в Консоли, зависит от того, как именно окно браузера было закрыто.


Если закрывать нажатием крестика в правом верхнем углу браузера или на единственной вкладке - в консоли пишется: "Webconsole context has changed".
Если закрывать нажатием Ctrl-F4 или Ctrl-W на единственной вкладке - в консоли пишется: "Webconsole context has changed".
Если закрывать нажатием Alt-F4 - в консоли тишина.
Если закрывать через пункт "Выход" в меню - консоль тоже закрывается.


Логику в этом можно усмотреть такую: если закрывают крестиком или клавиатурным сокращением, то это воспринимается как закрытие конкретного окна браузера, а пункт "Выход" означает закрытие не только браузера, но и всего-всего-всего (все другие окна браузера при этом тоже закрываются).


Выбивается из этой логики только Alt-F4: раз предупреждение "Webconsole context has changed" не появилось, значит с точки зрения Консоли что-то от того окна браузера ещё осталось работать. Что бы это могло быть и почему?

Отредактировано yup (30-01-2024 18:49:19)

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]