15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/urlmon_bind_status_callback.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mshtml.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlguid.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/bind_context_info.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/chrome_tab.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/exception_barrier.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/urlmon_moniker.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper to given feed data to the specified |bscb| using 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CacheStream instance. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT CacheStream::BSCBFeedData(IBindStatusCallback* bscb, const char* data, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size, CLIPFORMAT clip_format, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t flags, bool eof) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bscb) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "invalid IBindStatusCallback"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_INVALIDARG; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't use a CComObjectStackEx here since mshtml will hold 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // onto the stream pointer. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CComObject<CacheStream>* cache_stream = NULL; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = CComObject<CacheStream>::CreateInstance(&cache_stream); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CacheStream> cache_ref = cache_stream; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = cache_stream->Initialize(data, size, eof); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FORMATETC format_etc = { clip_format, NULL, DVASPECT_CONTENT, -1, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TYMED_ISTREAM }; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STGMEDIUM medium = {0}; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) medium.tymed = TYMED_ISTREAM; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) medium.pstm = cache_stream; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = bscb->OnDataAvailable(flags, size, &format_etc, &medium); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT CacheStream::Initialize(const char* cache, size_t size, bool eof) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_ = 0; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eof_ = eof; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = S_OK; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.reset(new char[size]); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cache_.get()) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(cache_.get(), cache, size); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = size; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "failed to allocate cache stream."; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = E_OUTOFMEMORY; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Read is the only call that we expect. Return E_PENDING if there 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is no more data to serve. Otherwise this will result in a 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// read with 0 bytes indicating that no more data is available. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP CacheStream::Read(void* pv, ULONG cb, ULONG* read) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pv || !read) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_INVALIDARG; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cache_.get()) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *read = 0; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_FALSE; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default to E_PENDING to signal that this is a partial data. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = eof_ ? S_FALSE : E_PENDING; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (position_ < size_) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *read = std::min(size_ - position_, size_t(cb)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(pv, cache_ .get() + position_, *read); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position_ += *read; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = S_OK; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////// 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT SniffData::InitializeCache(const std::wstring& url) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = url; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_type_ = UNDETERMINED; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kInitialSize = 4 * 1024; // 4K 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HGLOBAL mem = GlobalAlloc(0, kInitialSize); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(mem) << "GlobalAlloc failed: " << GetLastError(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = CreateStreamOnHGlobal(mem, TRUE, cache_.Receive()); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr)) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULARGE_INTEGER size = {0}; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_->SetSize(size); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "CreateStreamOnHGlobal failed: " << hr; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT SniffData::ReadIntoCache(IStream* stream, bool force_determination) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!stream) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_INVALIDARG; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = S_OK; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (SUCCEEDED(hr)) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t kChunkSize = 4 * 1024; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kChunkSize]; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD read = 0; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = stream->Read(buffer, sizeof(buffer), &read); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD written = 0; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_->Write(buffer, read, &written); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ += written; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((S_FALSE == hr) || !read) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool last_chance = force_determination || (size() >= kMaxSniffSize); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eof_ = force_determination; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DetermineRendererType(last_chance); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT SniffData::DrainCache(IBindStatusCallback* bscb, DWORD bscf, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLIPFORMAT clip_format) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_cache_valid()) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ideally we could just use the cache_ IStream implementation but 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can't use it here since we have to return E_PENDING for the 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last call 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HGLOBAL memory = NULL; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = GetHGlobalFromStream(cache_, &memory); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SUCCEEDED(hr) && memory) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* buffer = reinterpret_cast<char*>(GlobalLock(memory)); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = CacheStream::BSCBFeedData(bscb, buffer, size_, clip_format, bscf, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eof_); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GlobalUnlock(memory); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = 0; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.Release(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Scan the buffer or OptIn URL list and decide if the renderer is 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be switched. Last chance means there's no more data. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SniffData::DetermineRendererType(bool last_chance) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_undetermined()) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_chance) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_type_ = OTHER; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsChrome(RendererTypeForUrl(url_))) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_type_ = CHROME; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_cache_valid() && cache_) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HGLOBAL memory = NULL; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetHGlobalFromStream(cache_, &memory); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* buffer = reinterpret_cast<const char*>(GlobalLock(memory)); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring html_contents; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joshia): detect and handle different content encodings 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer && size_) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTF8ToWide(buffer, std::min(size_, kMaxSniffSize), &html_contents); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GlobalUnlock(memory); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that document_contents_ may have NULL characters in it. While 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // browsers may handle this properly, we don't and will stop scanning 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for the XUACompat content value if we encounter one. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring xua_compat_content; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UtilGetXUACompatContentValue(html_contents, &xua_compat_content); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StrStrI(xua_compat_content.c_str(), kChromeContentPrefix)) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_type_ = CHROME; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << "Url: " << url_ << base::StringPrintf( 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Renderer type: %s", renderer_type_ == CHROME ? "CHROME" : "OTHER"); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////// 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BSCBStorageBind::BSCBStorageBind() : clip_format_(CF_NULL) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BSCBStorageBind::~BSCBStorageBind() { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::for_each(saved_progress_.begin(), saved_progress_.end(), 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) utils::DeleteObject()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT BSCBStorageBind::Initialize(IMoniker* moniker, IBindCtx* bind_ctx) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << me() 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId()); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring url = GetActualUrlFromMoniker(moniker, bind_ctx, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring()); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = data_sniffer_.InitializeCache(url); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = AttachToBind(bind_ctx); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << __FUNCTION__ << me() << "AttachToBind error: " << hr; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!delegate()) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << __FUNCTION__ << me() << "No existing callback: " << hr; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_FAIL; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP BSCBStorageBind::OnProgress(ULONG progress, ULONG progress_max, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG status_code, LPCWSTR status_text) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ << me() 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << base::StringPrintf(" status=%i tid=%i %ls", status_code, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThread::CurrentId(), 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_text); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Report all crashes in the exception handler if we wrap the callback. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that this avoids having the VEH report a crash if an SEH earlier in 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the chain handles the exception. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExceptionBarrier barrier; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = S_OK; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(ananta) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ChromeFrame will not be informed of any redirects which occur while we 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // switch into Chrome. This will only break the moniker patch which is 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // legacy and needs to be deleted. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldCacheProgress(status_code)) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saved_progress_.push_back(new Progress(progress, progress_max, status_code, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_text)); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = CallbackImpl::OnProgress(progress, progress_max, status_code, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_text); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Refer to urlmon_moniker.h for explanation of how things work. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP BSCBStorageBind::OnDataAvailable(DWORD flags, DWORD size, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FORMATETC* format_etc, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STGMEDIUM* stgmed) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId()); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Report all crashes in the exception handler if we wrap the callback. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that this avoids having the VEH report a crash if an SEH earlier in 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the chain handles the exception. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExceptionBarrier barrier; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do not touch anything other than text/html. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_interesting = (format_etc && stgmed && stgmed->pstm && 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stgmed->tymed == TYMED_ISTREAM && 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsTextHtmlClipFormat(format_etc->cfFormat)); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_interesting) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Play back report progress so far. 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MayPlayBack(flags); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CallbackImpl::OnDataAvailable(flags, size, format_etc, stgmed); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = S_OK; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!clip_format_) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_format_ = format_etc->cfFormat; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_sniffer_.is_undetermined()) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool force_determination = !!(flags & 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = data_sniffer_.ReadIntoCache(stgmed->pstm, force_determination); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have sufficient data to determine renderer type 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wait for the next data notification. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_sniffer_.is_undetermined()) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!data_sniffer_.is_undetermined()); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_sniffer_.is_cache_valid()) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = MayPlayBack(flags); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!data_sniffer_.is_cache_valid()); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = CallbackImpl::OnDataAvailable(flags, size, format_etc, stgmed); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP BSCBStorageBind::OnStopBinding(HRESULT hresult, LPCWSTR error) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << __FUNCTION__ 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId()); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Report all crashes in the exception handler if we wrap the callback. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that this avoids having the VEH report a crash if an SEH earlier in 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the chain handles the exception. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExceptionBarrier barrier; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = MayPlayBack(BSCF_LASTDATANOTIFICATION); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = CallbackImpl::OnStopBinding(hresult, error); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseBind(); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Play back the cached data to the delegate. Normally this would happen 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when we have read enough data to determine the renderer. In this case 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we first play back the data from the cache and then go into a 'pass 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// through' mode. In some cases we may end up getting OnStopBinding 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before we get a chance to determine. Also it's possible that the 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BindToStorage call will return before OnStopBinding is sent. Hence 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is called from 3 places and it's important to maintain the 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exact sequence of calls. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Once the data is played back, calling this again is a no op. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT BSCBStorageBind::MayPlayBack(DWORD flags) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force renderer type determination if not already done since 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we want to play back data now. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_sniffer_.DetermineRendererType(true); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!data_sniffer_.is_undetermined()); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = S_OK; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_sniffer_.is_chrome()) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remember clip format. If we are switching to chrome, then in order 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to make mshtml return INET_E_TERMINATED_BIND and reissue navigation 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with the same bind context, we have to return a mime type that is 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // special cased by mshtml. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const CLIPFORMAT kMagicClipFormat = 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterClipboardFormat(CFSTR_MIME_MPEG); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_format_ = kMagicClipFormat; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!saved_progress_.empty()) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ProgressVector::iterator i = saved_progress_.begin(); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != saved_progress_.end(); i++) { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Progress* p = (*i); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't really expect a race condition here but just for sake 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of completeness we check. 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i) = NULL; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CallbackImpl::OnProgress(p->progress(), p->progress_max(), 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->status_code(), p->status_text()); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete p; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saved_progress_.clear(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_sniffer_.is_cache_valid()) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_sniffer_.is_chrome()) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<BindContextInfo> info; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BindContextInfo::FromBindContext(bind_ctx_, info.Receive()); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->SetToSwitch(data_sniffer_.cache_); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = data_sniffer_.DrainCache(delegate(), 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags | BSCF_FIRSTDATANOTIFICATION, clip_format_); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG_IF(WARNING, INET_E_TERMINATED_BIND != hr) << __FUNCTION__ << 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " mshtml OnDataAvailable returned: " << std::hex << hr; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We cache and suppress sending progress notifications till 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we get the first OnDataAvailable. This is to prevent 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mshtml from making up its mind about the mime type. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// However, this is the invasive part of the patch and 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// could trip other software that's due to mistimed progress 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notifications. It is probably not a good idea to hide redirects 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and some cookie notifications. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We only need to suppress data notifications like 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BINDSTATUS_MIMETYPEAVAILABLE, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BINDSTATUS_CACHEFILENAMEAVAILABLE etc. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is an atempt to reduce the exposure by starting to 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cache only when we receive one of the interesting progress 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notification. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BSCBStorageBind::ShouldCacheProgress(unsigned long status_code) const { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to cache progress notifications only if we haven't yet figured 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // out which way the request is going. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_sniffer_.is_undetermined()) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are already caching then continue. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!saved_progress_.empty()) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start caching only if we see one of the interesting progress 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notifications. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status_code) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BINDSTATUS_BEGINDOWNLOADDATA: 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BINDSTATUS_DOWNLOADINGDATA: 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BINDSTATUS_USINGCACHEDCOPY: 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BINDSTATUS_MIMETYPEAVAILABLE: 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BINDSTATUS_CACHEFILENAMEAVAILABLE: 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case BINDSTATUS_SERVER_MIMETYPEAVAILABLE: 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 428