При выборе «Ввод TextField» происходит нарушение защиты изолированной программной среды в загруженном SWF в Adobe AIR. - PullRequest
1 голос
/ 22 февраля 2011

У меня есть SWF, загруженный в изолированную программную среду вне приложения в Adobe AIR 1.5 (оболочка уже установлена ​​с нашими пользователями, поэтому я не могу обновить ее до версии 2+).

На этапе вSWF - это кнопки, видеоклипы, анимация и т. д. - все это прекрасно работает.

Когда мы добавляем входной TextField, выбор этого TextField приводит к нарушению изолированной программной среды безопасности.

Сообщение об ошибке (в режиме отладки): (я отредактировал фактические имена файлов):

[trace] *** Security Sandbox Violation ***
[trace] SecurityDomain 'file:///path/to/local/loaded.swf' tried to access incompatible context 'app:/loadingApp-debug.swf'

Пользователь не может ввести текст в TextField.На остальную часть приложения это не влияет.

В трассировке стека FDB отображаются только:

this = [Object 57216577, class='flash.utils::Timer'].Timer/tick() at <null>:0

У кого-нибудь есть обходной путь для этого?

Я предполагаю, что это либо TextField, пытающийся получить доступ к сцене, либо событие, пытающееся всплыть / получить доступ к глобальным свойствам.

Я понимаю ограничения воздушной песочницы и использую их ежедневно - с sandboxBridgesот родителя к ребёнку и от ребёнка к родителю и т. д. - может быть, мне нужно что-то раскрыть, чтобы это сработало?

Есть какие-нибудь подсказки?

Редактировать:

Теперь я обнаружил, что проблема заключается в том, что TextField пытается сделать

this.stage.focus = this;

или что-то эквивалентное, когда происходит MouseDown.

Также кажется, что нет доступа кKeyboardEvents в загруженных SWF-файлах, поэтому моя мысль о том, чтобы сделать «поле» кнопкой и затем управлять вводом путем прослушивания KeyboardEvents, мертва в воде.

Теперь рассмотрим, следует ли передавать события обратным вызовам, передаваемым через родительскую песочницу.бридж, или могут ли минимальные состязания спасти мою задницу.

1 Ответ

2 голосов
/ 23 февраля 2011

Хорошо, у меня безумный обходной путь, но он довольно солидный. Я собираюсь опубликовать это почти полностью здесь, хотя я, вероятно, сделаю его универсальным и в какой-то момент загрузлю его на github.

В моей оболочке у меня есть средство просмотра с посредником (я использую роботизированные ножки), которое я вызываю EventRelayer и EventRelayerMediator.

Единственная цель представления - предоставить посреднику доступ к сцене.

Я выставил некоторые функции parentSandboxBridge:

public function requestKeyboardEventRelay(eventType:String, callback:Function):void;

public function requestMouseEventRelay(eventType:String, callback:Function):void;

public function cancelKeyboardEventRelay(eventType:String, callback:Function):void;

public function cancelMouseEventRelay(eventType:String, callback:Function):void;

Мои мосты с песочницей всегда просто преобразуются в строго типизированные события, поэтому такие события пожара, как:

RelayEvent(RelayEvent.START_RELAY_REQUESTED, KeyboardEvent, eventType, callback);

RelayEvent(RelayEvent.CANCEL_RELAY_REQUESTED, MouseEvent, eventType, callback);

Они выбираются EventRelayerMediator и транслируются в обработчики в карте событий:

override public function onRegister():void
{           
    createRelayHandlerFactories();
    eventMap.mapListener(eventDispatcher, RelayEvent.START_RELAY_REQUESTED, startRelay);
}

protected function startRelay(e:RelayEvent):void
{
    var handler:Function = createRelayHandler(e.relayEventClass, e.callback);
    eventMap.mapListener(view.stage, e.relayEventType, handler, e.relayEventClass);
}

protected function createRelayHandler(relayEventClass:Class, callback:Function):Function
{
    var handler:Function = relayHandlerFactoriesByEventClass[relayEventClass](callback);

    return handler;
    }                  

protected function createRelayHandlerFactories():void
{
    relayHandlerFactoriesByEventClass = new Dictionary();
    relayHandlerFactoriesByEventClass[KeyboardEvent] = createKeyboardEventRelayHandler;
    relayHandlerFactoriesByEventClass[MouseEvent] = createMouseEventRelayHandler;
}                                                                                      

protected function createKeyboardEventRelayHandler(callback:Function):Function
{
    var handler:Function = function(e:KeyboardEvent):void
    {            
        trace("Relaying from shell: " + e.toString());
        // passing an object because the sandbox bridge doesn't allow strong typed values, only primitives
        var o:Object = {};
        o.type = e.type;
        o.charCode = e.charCode;
        o.keyCode = e.keyCode;
        o.altKey = e.altKey; 
        o.ctrlKey = e.ctrlKey;
        o.shiftKey = e.shiftKey;
        // no point adding other props as we can't pass them
        // to the constructor of the KeyboardEvent
        callback(o)
    } 

    return handler;
} 

Загруженный SWF передает обратный вызов, который просто повторно собирает и повторно отправляет события.

Мой ввод TextField теперь является просто динамическим полем с обработчиком щелчка, который активирует прослушивание событий клавиатуры в корне swf, а затем соответствующим образом обновляет динамическое поле.

В данный момент это супер-грубо, но я разбью его на надежный, проверенный класс, теперь я знаю, что это работает.

Я использовал словарь для управления обработчиками, потому что я уверен, что за этим последует адская утечка памяти, и я ожидаю, что придется передать FocusEvents, чтобы прекратить ввод текста.

Мне нужно проверить утечку памяти, вернуть привязку из функции parentSandboxBridge, чтобы я мог убедиться, что я не добавляю один и тот же обработчик дважды и т. Д. И т. Д., Но Adobe - вас отвратительно, если вы не вызываете это и не предоставляете встроенный релейный механизм.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...