次の方法で共有


Problems with Flash-content in the WebBrowser control

A recent case I worked on involved the following scenario.

Problem description

The client was building a kiosk-like application. I.e. a WinForms application with the WebBrowser control slapped onto it. The application worked fine for the most part, but they'd found that when viewing video via facebook they were only able to view the video the first time. Any additional attempt to view the video would fail with a custom error from the facebook application stating that the video was either restricted or no longer available.

This only happened when viewing the page via the WinForms application. Using IE directly worked just fine. We also found that this problem occurred with both IE7 and IE8 installed, so it seemed not to be related to the browser version.

Other sites using the Adobe Flash player to display video, such as MSN or Youtube worked just fine.

Troubleshooting

Using the Developer tools included in IE8 I found that the facebook application displays a placeholder image with a play-button. Once that button is clicked the .swf player is loaded via client-side script. The .swf player then downloads the .mp4 that is to be displayed and divides it into suitable chunks.

Fiddler traces revealed that the mp4 was downloaded when using IE but not when using the WinForms application. No errors were reported, instead the request was simply never made.

We removed all code behind. All that remained was the On_Load event that set a starting page for the WebBrowser control, still we were unable to successfully load the movie.

Adding facebook to the trusted zone changed nothing.

Using the COM-version of the WebBrowser control still reproduced the problem.

I then suspected restrictions in cross-domain access or similar, (facebook uses a lot of different domains,) but couldn't find anything conclusive.

Finally I stumbled upon the root cause.

Cause

The problem is due to a bug within the Adobe Flash-player: https://bugs.adobe.com/jira/browse/FP-256

The problem occurs when dynamically trying to display a cached .swf application with an external interface through script. So, another quick repro would be the following (Copied from the Adobe bug report):

  1. Create a C# application with an embedded WebBrowser control.
  2. Load a HTML page with no content.
  3. Via JavaScript, add a SWF with external interface to the page via an object tag. (At this point I see server traffic, requesting the SWF.)
  4. From JavaScript, access the external interface of the SWF. Works OK.
  5. Browse to a second web page.
  6. Browse back to the empty one.
  7. Via JavaScript, add the SWF again. Cannot contact the external interface. (There is no server traffic, indicating that the SWF is already being cached.)

Solution

While waiting for a fix from Adobe the only way to circumvent this is to manually remove the cached .swf. Article 262110 describes in detail how you can do this. Unfortunately this can be a bit tricky some times. In the sample repro above you'd resolve it by simply removing all .swf items from the cache upon page-load, but this wouldn't work in the facebook situation, since it might use the same control repeatedly without refreshing the page in between. Depending on your level of control over the target platform it might be easier to simply turn of caching.

/ Johan

Comments

  • Anonymous
    September 24, 2009
    Any idea whether Adobe is going to fix this issue?

  • Anonymous
    October 06, 2009
    Actually I don't. Looking at the link (http://bugs.adobe.com/jira/browse/FP-256) you'll find that others have asked Adobe the same question without response. / Johan

  • Anonymous
    October 29, 2009
    This also seems to work most of the time when placed at strategic locations, like OnBeforeNavigate2 (for top frame), OnFileDownload, and before calling Refresh. InternetSetOption(NULL, INTERNET_OPTION_RESET_URLCACHE_SESSION, NULL, 0); Bob

  • Anonymous
    September 28, 2010
    The comment has been removed

  • Anonymous
    September 28, 2010
    Stephen, I've not heard of any update to this problem. Here is my code for flushing the cache - it just flushes the appropriate type - seems to work OK - I've not found any flash videos that don't play... Bob // The purpose of this method is to prevent a bug with Adobe Flash player // not playing movies the second time. void CBrowserWindow::FlushSWFFilesFromCache() {  DWORD MAX_CACHE_ENTRY_INFO_SIZE = 4096;  DWORD dwEntrySize = MAX_CACHE_ENTRY_INFO_SIZE;  LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry;  //InternetSetOption(NULL, INTERNET_OPTION_RESET_URLCACHE_SESSION, NULL, 0);  lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];  lpCacheEntry->dwStructSize = dwEntrySize; again:  HANDLE hCacheDir = FindFirstUrlCacheEntryEx(NULL, 0, NORMAL_CACHE_ENTRY, 0, lpCacheEntry, &dwEntrySize, NULL, NULL, NULL);  if (hCacheDir == NULL)  {    switch (GetLastError())    {    case ERROR_NO_MORE_ITEMS:      delete[] (char*)lpCacheEntry;      return;    case ERROR_INSUFFICIENT_BUFFER:      delete[] (char*)lpCacheEntry;      lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];      lpCacheEntry->dwStructSize = dwEntrySize;      goto again;    default:      delete[] (char*)lpCacheEntry;      return;    }  }  do  {    if (lpCacheEntry->lpHeaderInfo)    {      TCHAR p = _tcsstr(lpCacheEntry->lpHeaderInfo, _T("Content-Type: "));      if (p)      {        p += 14;        if (!_tcsnicmp(p, _T("application/x-shockwave-flash"), 29))          DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);      }    }    // Reset entry size to the allocated size    dwEntrySize = max(MAX_CACHE_ENTRY_INFO_SIZE, lpCacheEntry->dwStructSize);    // and update the struct size    lpCacheEntry->dwStructSize = dwEntrySize; retry:    if (!FindNextUrlCacheEntry(hCacheDir, lpCacheEntry, &dwEntrySize))    {            switch (GetLastError())      {      case ERROR_NO_MORE_ITEMS:        FindCloseUrlCache(hCacheDir);        delete[] (char)lpCacheEntry;        return;      case ERROR_INSUFFICIENT_BUFFER:        delete[] (char*)lpCacheEntry;        lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];        lpCacheEntry->dwStructSize = dwEntrySize;        goto retry;      default:        FindCloseUrlCache(hCacheDir);        delete[] (char*)lpCacheEntry;        return;      }    }  } while (true);   }

  • Anonymous
    September 29, 2010
    The comment has been removed

  • Anonymous
    September 29, 2010
    Stephen, I guess that's helpful then if you are authoring the web page. Otherwise searching the DOM after download for such links and modifing the link could be an option? Is that how you see it? Bob

  • Anonymous
    August 31, 2015
    Hi, is there a way of flushing the cache, but leaving the cookies, as I need to keep the cookie info stored.. this stops the using cookies messages etc thanks