Disable flaky test ExtensionActionContextMenuTest.RunInspectPopup
[chromium-blink-merge.git] / chrome_frame / com_type_info_holder.cc
blobdd71ec06e6001ec31e62d5b243abfb30a5ca3005
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome_frame/com_type_info_holder.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
10 extern "C" IMAGE_DOS_HEADER __ImageBase;
12 namespace com_util {
14 base::LazyInstance<TypeInfoCache> type_info_cache = LAZY_INSTANCE_INITIALIZER;
16 // TypeInfoCache
18 TypeInfoCache::~TypeInfoCache() {
19 CacheMap::iterator it = cache_.begin();
20 while (it != cache_.end()) {
21 delete it->second;
22 it++;
26 TypeInfoNameCache* TypeInfoCache::Lookup(const IID* iid) {
27 DCHECK(Singleton() == this);
29 TypeInfoNameCache* tih = NULL;
31 base::AutoLock lock(lock_);
32 CacheMap::iterator it = cache_.find(iid);
33 if (it == cache_.end()) {
34 tih = new TypeInfoNameCache();
35 HRESULT hr = tih ? tih->Initialize(*iid) : E_OUTOFMEMORY;
36 if (SUCCEEDED(hr)) {
37 cache_[iid] = tih;
38 } else {
39 NOTREACHED();
40 delete tih;
41 tih = NULL;
43 } else {
44 tih = it->second;
47 return tih;
50 TypeInfoCache* TypeInfoCache::Singleton() {
51 return type_info_cache.Pointer();
54 HRESULT TypeInfoNameCache::Initialize(const IID& iid) {
55 DCHECK(type_info_ == NULL);
57 wchar_t file_path[MAX_PATH];
58 DWORD path_len = ::GetModuleFileNameW(reinterpret_cast<HMODULE>(&__ImageBase),
59 file_path, arraysize(file_path));
60 if (path_len == 0 || path_len == MAX_PATH) {
61 NOTREACHED();
62 return E_UNEXPECTED;
65 base::win::ScopedComPtr<ITypeLib> type_lib;
66 HRESULT hr = LoadTypeLib(file_path, type_lib.Receive());
67 if (SUCCEEDED(hr)) {
68 hr = type_lib->GetTypeInfoOfGuid(iid, type_info_.Receive());
71 return hr;
74 // TypeInfoNameCache
76 HRESULT TypeInfoNameCache::GetIDsOfNames(OLECHAR** names, uint32 count,
77 DISPID* dispids) {
78 DCHECK(type_info_ != NULL);
80 HRESULT hr = S_OK;
81 for (uint32 i = 0; i < count && SUCCEEDED(hr); ++i) {
82 NameToDispIdCache::HashType hash = NameToDispIdCache::Hash(names[i]);
83 if (!cache_.Lookup(hash, &dispids[i])) {
84 hr = type_info_->GetIDsOfNames(&names[i], 1, &dispids[i]);
85 if (SUCCEEDED(hr)) {
86 cache_.Add(hash, dispids[i]);
91 return hr;
94 HRESULT TypeInfoNameCache::Invoke(IDispatch* p, DISPID dispid, WORD flags,
95 DISPPARAMS* params, VARIANT* result,
96 EXCEPINFO* excepinfo, UINT* arg_err) {
97 DCHECK(type_info_);
98 HRESULT hr = type_info_->Invoke(p, dispid, flags, params, result, excepinfo,
99 arg_err);
100 DCHECK(hr != RPC_E_WRONG_THREAD);
101 return hr;
104 // NameToDispIdCache
106 bool NameToDispIdCache::Lookup(HashType hash, DISPID* dispid) const {
107 base::AutoLock lock(lock_);
108 const DispidMap::const_iterator it = map_.find(hash);
109 bool found = (it != map_.end());
110 if (found)
111 *dispid = it->second;
112 return found;
115 void NameToDispIdCache::Add(HashType hash, DISPID dispid) {
116 base::AutoLock lock(lock_);
117 map_[hash] = dispid;
120 NameToDispIdCache::HashType NameToDispIdCache::Hash(const wchar_t* name) {
121 return LHashValOfName(LANG_NEUTRAL, name);
124 } // namespace com_util