Это, вероятно, намного больше информации, чем вы хотели.
Что касается механики, GWT захватывает пользовательский агент из браузера, а затем использует механизм, называемый "поставщиком свойств", для классификации браузера.Таким образом, поставщик свойств устанавливает свойство с именем «user.agent» для одного из нескольких предопределенных классов браузеров.
Вот файл XML, который определяет константы для всех классов браузеров, о которых в настоящее время знает GWT:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/UserAgent.gwt.xml?
Во время компиляции ваше приложение компилируется отдельно для каждого класса браузера, который вы хотите поддерживать, и для каждого типа браузера загружается отдельная партия JS.Прелесть этого в том, что конечный пользователь загружает минимальный объем кода, необходимый для запуска приложения, и не будет раздутым, если у вас будет условный код для IE, когда вы работаете в Chrome или Firefox.
Немногосложный, но вы можете взглянуть на код, который записывает некоторый JavaScript, чтобы проверить строку User Agent, чтобы определить, какой класс браузера работает в данный момент:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/rebind/UserAgentPropertyGenerator.java
Как только он выберетзначение для свойства user.agent, различные части GWT условно подставляются в код, где необходима специфическая для браузера логика.Большинство браузеров возвращают длинный список «совместимых» пользовательских агентов.GWT пытается выбрать лучший матч из тех.Вы можете видеть, что есть случай по умолчанию - если строка пользовательского агента вообще не распознается, он устанавливает значение user.agent в значение «unknown» и выдает предупреждение, чтобы предупредить, что разработчик должен выбрать один вручную.
Чтобы погрузиться немного глубже, вот механизм, который компилятор использует для извлечения специфичного для браузера кода на основе свойства user.agent:
(из Window.gwt.xml)
<module>
<inherits name="com.google.gwt.core.Core"/>
<inherits name="com.google.gwt.user.UserAgent"/>
<replace-with class="com.google.gwt.user.client.impl.WindowImplIE">
<when-type-is class="com.google.gwt.user.client.impl.WindowImpl"/>
<any>
<when-property-is name="user.agent" value="ie6"/>
<when-property-is name="user.agent" value="ie8"/>
<when-property-is name="user.agent" value="ie9"/>
</any>
</replace-with>
</module>
Вы заметите, что если в пользовательском агенте отображается «webkit», GWT возвращает строку «safari», чтобы идентифицировать класс браузера.Для Chrome нет отдельного класса браузеров.Chrome и Safari очень похожи и довольно близко написаны к спецификациям, поэтому для них не так уж много специальных корпусов.Но это не значит, что в некоторых местах нет специального кода для Chrome.Иногда разница в браузере будет обнаружена во время выполнения.Это делается только тогда, когда есть небольшие различия в браузере.Вот пример того, как обрабатывается небольшая разница между Chrome и Safari:
public class HyperlinkImplSafari extends HyperlinkImpl {
private static boolean shiftIsModifier = onChrome();
private static native boolean onChrome() /*-{
return navigator.userAgent.indexOf("Chrome") != -1;
}-*/;
@Override
public boolean handleAsClick(Event event) {
//...
boolean modifiers = alt || ctrl || meta;
if (shiftIsModifier) {
modifiers |= shift;
}
return !modifiers && !middle && !right;
}
}