TChromium Options - опции в инспекторе объектов
Рассмотрим и потестируем некоторые опции компонента TChromium.
На момент тестов (июль 2016) автор использовал конфигурацию: Lazarus IDE v1.6.0, fpc 3.0.0, fpCEF3 3.2526, win7 64.
В сентябре 2016 автор сменил версию fpCEF3 на 3.2704, пока изменений в тестах не заметил.
В новых версиях fpCEF3 (например в 3.2924 - Chromium 56.0.2924.76), некоторые свойства удалены.
Вы можете сразу перейти к разделу с результатами и подробным описанием.
У меня сложилось подозрение, что некоторые опции вообще не поддерживаются, несмотря на их наличие и описание. Это не касается FontOptions - они даже в исходниках описаны куда лучше и полнее.
Если Вы заметили ошибку или неточность, просьба сообщить об ошибке.
Свойства Options применяются при инициализации компонента TChromium (при старте обработки событий).
Независимо от смены URL или создания объектов браузера (окон), значения опций TChromium остаются одинаковыми.
В файле cef3types.pas Options описаны через PCefBrowserSettings / TCefBrowserSettings.
Так же в файле cef3gui.pas см. описание TChromiumOptions.
Создадим простейший тестовый проект - одну главную форму с единственным контролом - компонентом TChromium
Создадим локальный файл test.html
Будем менять опции в инспекторе объектов и содержимое файла test.html, после чего смотреть что у нас изменилось.
(если вы ещё не подключили fpCEF3, то узнайте как это сделать: подключение веб-браузера в Lazarus).
Для навигации по всем страницам этого раздела сайта используйте иконку меню или ссылку Навигация в строке навигации.
Lazarus Тестовый проект
Свойства формы:
- Name : FormTest
- Position : poDesktopCenter
- Width / Height соответственно 800 и 600
Свойства TChromium:
- Anchors : [akTop,akLeft,akRight,akBottom]
- Width / Height - соответственно 800 и 600
- Options : ... будем менять и тестировать
test.lpr
program test;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, Unit1
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource := True;
Application.Initialize;
Application.CreateForm(TFormTest, FormTest);
Init;
Application.Run;
end.
unit1.pas
unit Unit1;
interface
{$mode objfpc}{$H+}
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, cef3lcl { ,synacode };
type
{ TFormTest }
TFormTest = class(TForm)
Chromium1: TChromium;
private
{ private declarations }
public
{ public declarations }
end;
var
FormTest: TFormTest;
procedure Init;
implementation
{$R *.lfm}
procedure Init;
var Url: String;
begin
Url := ExtractFileDir(Application.ExeName) + '\test.html';
if (FileExists(Url)) then
{ Если путь содержит кириллицу или спецсимволы, используйте EncodeURL(Url) модуля synacode }
FormTest.Chromium1.Load(Url);
end;
end.
Тестовый файл test.html
<!DOCTYPE html>
<html>
<head>
<title>Test TChromium Options</title>
<meta http-equiv = "Content-Type" content = "text/html; charset=utf-8">
<style>
* { margin:0; padding:0; font:inherit; color:inherit; outline:none; }
html, body { width:100%; height:100%; } body { background:#eeeeee; }
/* Контейнер страницы */
#main { position:relative; margin:0 auto; max-width:800px; min-width:480px; min-height:100%; background:#ffffff; }
/* Блок контента */
#content { position:relative; min-height:100px; }
/* отступы сверху и снизу от Блока контента */
#sHeader, #sFooter { position:relative; height:100px; }
/* Заголовок страницы */
#header { position:absolute; top:0; left:0; right:0; height:100px; background:#c8c8c8; }
/* Подвал страницы */
#footer { position:relative; margin:-99px auto 0 auto; max-width:800px; min-width:480px; height:100px; background:#c8c8c8; }
</style>
<script>
function getId(node) { /* Cсылка на объект по его id */
return typeof node == "object" ? node : document.getElementById(node);
}
document.addEventListener("DOMContentLoaded", init, false);
function init() {
/* Здесь будем работать с веб-страницей */
}
</script>
</head>
<body>
<div id="main">
<div id="sHeader"></div>
<div id="content">Контент Контент Контент</div>
<div id="sFooter"></div>
<div id="header"></div>
</div>
<div id="footer"></div>
</body>
</html>
Подробное описание Options
После тестов я подозреваю, что некоторые опции не поддерживаются, несмотря на их наличие и описание.
Это не касается FontOptions - они даже в исходниках fpCEF3 описаны куда лучше и полнее.
Если Вы заметили ошибку или неточность, просьба сообщить об ошибке.
Свойства Options применяются при инициализации компонента TChromium (при старте обработки событий приложением).
Независимо от смены URL или открытия веб-страниц в новых объектах браузера (окнах), значения опций TChromium остаются одинаковыми.
В файле cef3types.pas Options описаны через PCefBrowserSettings / TCefBrowserSettings.
Так же в файле cef3gui.pas см. описание TChromiumOptions.
Я не нашёл программного способа менять значения опций, только через IDE или через файл описания формы *.lfm
В таблице ниже приведены Названия опций в инспекторе объектов и их Краткое описание.
Инспектор объектов | Краткое описание |
---|---|
ApplicationCache | Использование технологии Application Cache |
CaretBrowsing | --- Удалено в новых версиях fpCEF3 --- |
Databases | Возможность использования Web Sql Database |
FileAccessFromFileUrls | --- |
ImageLoading | Управление возможностью загрузки и показа изображений |
ImageShrinkStandaloneToFit | --- |
Java | В Chromium с версии 42 не поддерживается, в TCefBrowserSettings поле отсутствует --- В новых версиях fpCEF3 это свойство удалено --- |
Javascript | Возможность выполнения JavaScript |
JavascriptAccessClipboard | Возможность копирования в буфер обмена через JavaScript-код |
JavascriptCloseWindows | Возможность закрывать окна из JavaScript (которые были открыты не из JavaScript) |
JavascriptDomPaste | Возможность вставки из буфера обмена через JavaScript-код |
JavascriptOpenWindows | Возможность открывать окна из JavaScript |
LocalStorage | Возможность использования локального хранилища из JavaScript |
Plugins | Возможность загрузки плагинов (не тестировалось) |
RemoteFonts | Управляет загрузкой шрифтов из удаленных источников |
TabToLinks | Возможность выделения ссылок клавишей Tab |
TextAreaResize | Возможность изменения размера textarea пользователем |
UniversalAccessFromFileUrls | --- |
Webgl | Поддержка WebGL |
WebSecurity | --- |
ApplicationCache
Для проверки пришлось перенести локальный html-файл на сайт и добавить подключаймый файл manifest.appcache, который отдавался с заголовком Content-Type: text/cache-manifest
При установке значения STATE_DISABLED код ниже выдавал "Not cached", в остальных случаях "Checking",
далее я не стал копаться, так как опция работает.
...
<html manifest="manifest.appcache">
...
function init() {
/* Проверка работы Application Cache */
var sCacheStatus = "Not supported";
var oAppCache = window.applicationCache;
switch ( oAppCache.status ) {
case oAppCache.UNCACHED :
sCacheStatus = "Not cached";
break;
case oAppCache.IDLE :
sCacheStatus = "Idle";
break;
case oAppCache.CHECKING :
sCacheStatus = "Checking";
break;
case oAppCache.DOWNLOADING :
sCacheStatus = "Downloading";
break;
case oAppCache.UPDATEREADY :
sCacheStatus = "Update ready";
break;
case oAppCache.OBSOLETE :
sCacheStatus = "Obsolete";
break;
default :
sCacheStatus = "Unexpected Status ( " + oAppCache.status.toString() + ")";
break;
} alert( sCacheStatus );
}
...
Подробнее про Application Cache API можно почитать MSDN или 4.6.2. Application caches
CaretBrowsing
Это свойство удалено в новых версиях fpCEF3, а ранее не было поддержки.
Режим активного курсора. В браузерах обычно включается клавишей F7.
Мы можем любой HTML-блок сделать редактируемым через JavaScript:
...
function init() {
/* Редактирование HTML-блока */
getId("main").contentEditable = true;
/* Можно написать и так: */
getId("main")["contentEditable"] = true;
/* и так: */
getId("main").setAttribute("contentEditable", true);
}
...
Это работает в любом браузере, в том числе и в Chromium.
Databases
При установке значения STATE_DISABLED, Web Sql Database не поддерживается.
Значение опции НЕ влияет на поддержку IndexedDB, если верить поверхностной проверке:
...
function init() {
/* Проверка работы опции Databases */
var text = "";
text += "<br>Web Sql Database : " + (window["openDatabase"] ? "Enabled" : "Disabled");
text += "<br>IndexedDB : " + (window["IndexedDB"] ? "Enabled" : "Disabled");
getId("header").innerHTML = text;
}
...
Детальней не разбирался, потому что мне вполне хватает LocalStorage.
FileAccessFromFileUrls
Тестировал, но разницы в работе не увидел (аналогично опции UniversalAccessFromFileUrls).
Вне зависимости от установки этой опции, локальная страница может обращаться как к локальным, так и сетевым файлам, но сетевая страница не может обратиться напрямую к локальным файлам. FileAPI и DragDrop работают всегда, но это действия пользователя...
Тестировал через добавление JS-скрипта, как через ссылку в исходном HTML-коде, так и через JS-код добавления нового скрипта.
Тестировал через ссылку на изображение img, добавленную в исходный HTML-код страницы.
ImageLoading
Загрузка и показ изображений, как из сети, так и локальных. Как в исходном html-коде, так и через JavaScript.
При установке значения STATE_DISABLED изображения на веб-страницах не отображаются (кроме формата base64). Можно проверить:
...
function init() {
/* Проверка работы опции ImageLoading */
var node = getId( "main" ),
img = document.createElement( "img" );
img.src = "http://site.../image.gif"; /* или локальный */
/* img.src = "data:image/png;base64,iVBORw0 ... "; */
node.appendChild( img );
}
...
Нет никакой разницы, где задаются изображения (в CSS, HTML, JavaScript) - показ изображений зависит от установленной опции.
Важно! Эта опция не влияет на изображения в формате base64, как в CSS, так и в JS или в исходном HTML-коде.
ImageShrinkStandaloneToFit
Специально не тестировал, только попутно с другими опциями и тестами. После смены значений этой опции, отличий в работе не замечал.
Java
В Chromium с версии 42 не поддерживается. Видимо, оставлено для совместимости со старыми проектами.
В новых версиях fpCEF3 это свойство вообще удалено.
Javascript
Возможность выполнения JavaScript.
При установке значения STATE_DISABLED яваскрипты не работают.
JavascriptAccessClipboard
Копирование в буфер обмена из JS-кода зависит от этой опции. Можно оставить значение по умолчанию STATE_DEFAULT.
Копирование в буфер обмена работает независимо от действий пользователя, то-есть в любой момент «по желанию» JS-кода.
Если присвоить STATE_DISABLED, то копирование в буфер и вставка из буфера обмена через JavaScript-код работать не будет
(опция JavascriptDomPaste - вставка из буфера обмена, зависит от этой опции). Можно потестировать:
...
function init() {
/*
Проверка работы опции JavascriptAccessClipboard
Копирование в буфер обмена в произвольный момент,
в данном случае сразу после загрузки страницы.
*/
var successful,
node = getId( "content" ),
selection = window.getSelection(),
range = document.createRange();
document.addEventListener("keyup", function(e) {
/* Перезагрузка страницы F5 */
if (e.keyCode==116) window.location.reload();
}, false);
node.contentEditable = true;
node.focus();
range.selectNodeContents( node );
selection.removeAllRanges();
selection.addRange( range );
successful = document.execCommand( "copy" ); /* "cut" и др. */
getId("header").innerHTML = "copy : " + successful;
selection.removeAllRanges();
}
...
После загрузки (перезагрузки) страницы, в буфер копируется содержимое блока "content" (если опция JavascriptAccessClipboard задана со значением, отличным от STATE_DISABLED). Это можно проверить через <Ctrl + V> - блок редактируемый.
Можно поэкспериментировать с поддержкой различных команд: execCommand
Важно! При работе с произвольными веб-страницами из своего приложения, если вы не хотите, чтобы вам «гадили» в буфер обмена, устанавливайте значение этой опции как STATE_DISABLED.
JavascriptCloseWindows
При установке значения STATE_DISABLED, JavaScript код window.close() не выполняет закрытие окна (главного или формы).
Разумеется, если новое окно было открыто из JS-кода, то эта опция не действует и окно может быть закрыто через ссылку на него из JavaScript.
Новые объекты-окна так же закрываются из JS-кода, вне зависимости от значений опции JavascriptCloseWindows.
Поэтому рекомендую ставить STATE_DISABLED, если форма (особенно главная форма) не должна быть закрыта из JS.
Узнать текущие значения опций можно в функции - обработчике события OnBeforePopup (перед открытием нового объекта-окна).
...
function init() {
/* Проверка работы опции JavascriptCloseWindows */
setTimeout( function() { window.close() } , 3000 );
}
...
Внимание! При запуске приложения, на стартовой веб-странице, JavaScript-код window.close(), независимо от значения опции, всегда закрывает окно (или всё приложение, если компонент TChromium находится на главной форме).
Поэтому не исключено, что придётся выдавать дополнительный диалог подтверждения операции, что напрягает пользователя, когда он сам закрывает окно. Или необходимо сменить URL после Application.Run; (когда приложение уже «слушает» и обрабатывает события).
Вне зависимости от установленной опции, отловить попытку закрытия любого объекта (окна) можно в функции - обработчике события onClose.
JavascriptDomPaste
Для возможности вставки из буфера обмена через JavaScript-код, опция должна иметь значение STATE_ENABLED,
при этом значение опции JavascriptAccessClipboard НЕ должно быть STATE_DISABLED.
Вставка из буфера обмена работает независимо от действий пользователя, то-есть в любой момент «по желанию» JS-кода.
...
function init() {
/*
Проверка работы опции JavascriptDomPaste
Вставка из буфера обмена в произвольный момент,
в данном случае сразу после загрузки страницы.
Вставка из буфера обмена по клику в блоке "content".
*/
var node = getId( "content" );
node.contentEditable = true;
node.addEventListener("click", oper, false);
document.addEventListener("keyup", function(e) {
/* Перезагрузка страницы F5 */
if (e.keyCode==116) window.location.reload();
}, false);
oper();/* немедленная вставка */
}
function oper(e) {
var successful;
getId( "content" ).focus();
successful = document.execCommand("paste", false, null);
getId("header").innerHTML = "paste : " + successful;
}
...
После загрузки (перезагрузки) страницы, а так же по клику, в блок "content" происходит вставка из буфера обмена.
Опция JavascriptAccessClipboard должна быть задана со значением, отличным от STATE_DISABLED,
опция JavascriptDomPaste должна быть задана со значением STATE_ENABLED.
Важно! При работе с произвольными веб-страницами из своего приложения, если вы не хотите, чтобы у вас воровали данные из буфера обмена, НЕ устанавливайте значение этой опции как STATE_ENABLED.
JavascriptOpenWindows
При значении по умолчанию (STATE_DEFAULT) новые объекты-окна открываются и закрываются с помощью JavaScript-кода.
При установке значения STATE_DISABLED объект-окно не открывается.
...
function init() {
/* Проверка работы опции JavascriptOpenWindows */
var objWin = window.open( "about:blank" );
if ( objWin ) {
/* objWin == [object Window] */
setTimeout( function() { objWin.close() } , 3000 );
} else {
/* objWin == undefined */
alert( "STATE_DISABLED" );
}
}
...
Окно с объектом браузера, открытое таким образом, может быть закрыто в любой момент через сохранённую ссылку objWin.close(), независимо от его текущего положения и видимости (например, если окно было распахнуто на весь экран или свёрнуто пользователем).
LocalStorage
Возможность использования локального хранилища из JavaScript.
При установке значения STATE_DISABLED не поддерживается. Можно проверить:
...
function init() {
/* Проверка работы опции LocalStorage */
alert( window.localStorage );
/* или так */
alert( window["localStorage"] );
}
}
...
При STATE_DISABLED объекта [object Storage] не существует (null).
Plugins
Не тестировал и пока не планирую.
Возможно подключение pepper-flash, libpdf и т.д.
RemoteFonts
Возможность загрузки сторонних шрифтов.
При установке значения STATE_DISABLED, шрифты не будут подгружаться, это можно проверить, изменив исходный HTML-код:
...
<link rel = "stylesheet" type = "text/css" href = "http://fonts.googleapis.com/css?family=Roboto:400&subset=latin,cyrillic">
<style>
...
#content { position:relative; min-height:100px; font-family:Roboto; }
...
Загрузка внешних шрифтов замедляет отображение веб-страницы, даже если их подгружать перед завершающим тегом «body».
TabToLinks
Возможность выделения ссылок клавишей Tab.
При установке значения STATE_DISABLED ссылки не выделяются и работают только по клику.
TextAreaResize
Возможность изменения размера textarea пользователем.
При установке значения STATE_DISABLED размеры области ввода textarea не могут быть изменены пользователем.
Существут ещё один способ убрать пользовательское изменение размеров - это установка одинаковых значений для CSS-стилей min-width, width, max-width (и соответственно min-height, height, max-height), или установка одинаковых значений стилей объекта из JavaScript.
UniversalAccessFromFileUrls
Тестировал, но разницы в работе не увидел (аналогично опции FileAccessFromFileUrls).
Вне зависимости от установки этой опции, локальная страница может обращаться как к локальным, так и сетевым файлам, но сетевая страница не может обратиться напрямую к локальным файлам. FileAPI и DragDrop работают всегда, но это действия пользователя...
Тестировал через добавление JS-скрипта, как через ссылку в исходном HTML-коде, так и через JS-код добавления нового скрипта.
Тестировал через ссылку на изображение img, добавленную в исходный HTML-код страницы.
Webgl
Поддержка WebGL.
При установке значения STATE_DISABLED WebGL не работает (например, 3D тест работать не будет).
WebSecurity
Немного тестировал. Не видел изменений в работе.
Установка STATE_DISABLED не влияет на запрет обращения к локальным файлам из сетевой страницы.
Не думаю, что отключение защиты будет хорошей идеей.