Управление WebBrowser и тегом Embed
Я полагаю, что у меня проблема с безопасностью, связанная с использованием тега embed с элементом управления WebBrowser в моем приложении WinForms С# 2008.
Вот мой код:
private void button2_Click(object sender, EventArgs e)
{
webBrowser1.Navigate("C:/page1.html");
}
private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Navigate("about:blank");
Thread.Sleep(1000);
webBrowser1.Document.Write("<html><body><p>Hello</p><embed src='C:/test.wmv' /></body></html>");
}
Это содержимое страницы1.html:
<html><body><p>Hello</p><embed src='C:/test.wmv' /></body></html>
Button1 генерирует слово "Hello".
Button2 генерирует слово "Hello" со встроенным проигрывателем фильма под ним.
Когда я просматриваю источники для обеих страниц, я заметил, что они идентичны, за исключением имени исходного файла.
Это заставляет меня думать, что это как-то связано с моими настройками безопасности IE, но я замечаю, что у меня есть полные разрешения для встроенного контента. Возможно, элемент управления не распознает источник страницы как правильный и, следовательно, не позволяет использовать тег embed.
Как я могу преодолеть это программно? Я хочу избежать записи моей страницы в файл и навигации по этому файлу любой ценой. Любые предложения о том, как обмануть управление браузером в правильной работе?
1-й редактор:
В соответствии с этой статьей Webbrowser Navigate Embedded Ресурс, это будет работать, но я (JT) попытался, и он не сделал этого:
System.IO.Stream stream = this.GetType().Assembly.GetManifestResourceStream("WindowsFormsApplication1.Properties.test.html");
webBrowser1.DocumentStream = stream;
Нечетное поведение при воспроизведении проблемы:
webBrowser1.Navigate("about:blank");
do
{
Thread.Sleep(100);
} while (webBrowser1.IsBusy == true);
//Method 1. Doesn't work
string htmlString1 = File.ReadAllText("C:/page1.html");
webBrowser1.Document.Write(htmlString1);
//Method 2. Doesn't work
string htmlString2 = "<html><body><p>Hello</p><embed src='C:/test.wmv' /></body></html>";
webBrowser1.Document.Write(htmlString2);
//Method 3. DOES WORK
webBrowser1.Document.Write("<html><body><p>Hello</p><embed src='C:/test.wmv' /></body></html>");
Изменить 2
Вот пример страницы, созданной с использованием JavaScript, без реального исходного файла, который отображает встроенный проигрыватель в IE:
<html><head>
<script language="JavaScript">
function go()
{
test1 = window.open("","","menubar=0,status=0,toolbar=0");
test1.document.writeln("<html><body><p>Hello</p><embed src='test.wmv' /></body></html>");
}
</script>
</head><body><h1 onclick="go()">click</h1></body></html>
Единственное отличие здесь в том, что IE считает, что источником HTML является файл, хотя он создан "writeln".
Хотя популярно мнение, что IE не поддерживает тег, он делает, и есть много примеров, подтверждающих это. Попытка с IE на jsfiddle.net в IE будет играть встроенный плеер, а в FF этого не будет.
Изменить 3
Эта проблема связана с междоменной безопасностью. Не только новые версии IE отказываются разрешать любые изменения в домене страницы, как только он существует, элемент управления WebBrowser не позволяет вам писать текст в документ, в котором уже есть текст. Только первый вызов Document.Write делает что угодно. Мало того, что нет видимого способа заставить домен страницы, также нет способа написать что-либо новое на странице с доменом, который установлен, потому что "openNew", которое требуется для записи, открывается примерно: пустым и по умолчанию является нулевой домен, который вызывает исключения, если задано или получено попытка.
Изменить 4
Проблема заключается в уязвимости в междоменной безопасности. См. ЭТО IE8 решил, что Document.Domain не может быть записано. Даже если он доступен для записи, вы, по-видимому, никогда не обмениваетесь сообщениями между протоколами. Таким образом, протокол "file://" и протокол "about" не могут связываться или иметь теги, указывающие друг на друга. Вот камни преткновения:
- Версия IE, используемая браузером, не может ничего сделать для
Document.Domain, даже с JavaScript.
- Вы не можете прочитать домен около: blank.
- Вы не можете загрузить страницу с надлежащим доменом и ожидать использования
Document.Write, чтобы написать HTML в него, потому что вы вынуждены звонить
Document.OpenNew перед использованием Document.Write.
- Вы не можете изменить DocumentText с помощью WebBrowser.DocumentText =
ничего, потому что вы можете установить только DocumentText только один раз для каждой навигации. Это похоже на некоторые другие вещи безопасности.
В заключение достаточно сказать, что у вас нет дополнительного контроля над безопасностью с помощью элемента управления WebBrowser, вероятно, даже меньше, чем у вас с некоторыми страницами, генерируемыми JavaScript (поскольку эти страницы разделяют домен запуска script).
Спасибо за голоса/поддержку в моих усилиях, но похоже, что я собираюсь отказаться и написать страницу в файл каждый раз, когда я хочу изменить то, что находится в управлении браузером. Тьфу.
Ответы
Ответ 1
Проблема заключается в уязвимости в междоменной безопасности. См. ЭТО IE8 решил, что Document.Domain не может быть записано. Даже если он доступен для записи, вы, по-видимому, никогда не обмениваетесь сообщениями между протоколами. Таким образом, протокол "file://" и протокол "about" не могут связываться или иметь теги, указывающие друг на друга. Вот камни преткновения:
- Версия IE, используемая браузером, не может ничего сделать для
Document.Domain, даже с JavaScript.
- Вы не можете прочитать домен около: blank.
- Вы не можете загрузить страницу с надлежащим доменом и ожидать использования
Document.Write, чтобы написать HTML в него, потому что вы вынуждены звонить
Document.OpenNew перед использованием Document.Write.
- Вы не можете изменить DocumentText с помощью WebBrowser.DocumentText =
ничего, потому что вы можете установить только DocumentText только один раз для каждой навигации. Это похоже на некоторые другие вещи безопасности.
В заключение достаточно сказать, что у вас нет дополнительного контроля над безопасностью с помощью элемента управления WebBrowser, вероятно, даже меньше, чем у вас с некоторыми страницами, генерируемыми JavaScript (поскольку эти страницы разделяют домен запуска script).
Спасибо за голоса/поддержку в моих усилиях, но похоже, что я собираюсь отказаться и написать страницу в файл каждый раз, когда я хочу изменить то, что находится в управлении браузером. Тьфу.
Ответ 2
Вот почему:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd562847(v=vs.85).aspx
Предыдущие примеры работают в Firefox, но не в Internet Explorer. Чтобы встроить элемент управления Player в веб-страницу, которая может быть отображена Internet Explorer, вы должны создать элемент OBJECT, который имеет Атрибут classid, присвоенный идентификатору класса проигрывателя Windows Media Player контроль. В следующем примере показано, как встраивать проигрыватель Windows Media контроль на веб-странице, которая может отображаться корректно с помощью Интернета Explorer и Firefox. Script на странице определяется тип браузера и генерирует соответствующий тег OBJECT.
Для вашего удобства здесь:
private void button3_Click(object sender, EventArgs e)
{
webBrowser1.Navigate("about:blank");
do
{
Thread.Sleep(100);
} while (webBrowser1.IsBusy == true);
string htmlString1 = File.ReadAllText("C:/test.html");
webBrowser1.Document.Write(htmlString1);
return;
}
Содержимое Test.html:
<OBJECT id="VIDEO" width="320" height="240"
style="position:absolute; left:0;top:0;"
CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"
type="application/x-oleobject">
<PARAM NAME="URL" VALUE="c:\test.wmv">
<PARAM NAME="SendPlayStateChangeEvents" VALUE="True">
<PARAM NAME="AutoStart" VALUE="True">
<PARAM name="uiMode" value="none">
<PARAM name="PlayCount" value="9999">
</OBJECT>
Ответ 3
@GorchestopherH это позор, чтобы услышать результат. Возможно, вы захотите поставить четвертое редактирование в качестве ответа - было бы позором потерять награду в 50 пунктов в целом.
Другим решением является другой элемент управления веб-браузером: http://code.google.com/p/geckofx/
Вставка Firefox Brower в С# с помощью GeckoFX