- add sources.
[platform/framework/web/crosswalk.git] / src / chrome_frame / urlmon_moniker.h
1 // Copyright (c) 2010 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.
4
5 #ifndef CHROME_FRAME_URLMON_MONIKER_H_
6 #define CHROME_FRAME_URLMON_MONIKER_H_
7
8 #include <atlbase.h>
9 #include <atlcom.h>
10 #include <urlmon.h>
11 #include <string>
12
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/threading/thread_local.h"
16 #include "base/win/scoped_variant.h"
17 #include "chrome_frame/utils.h"
18
19 // This file contains classes that are used to cache the contents of a top-level
20 // http request (not for sub frames) while that request is parsed for the
21 // presence of a meta tag indicating that the page should be rendered in CF.
22
23 // Here are a few scenarios we handle and how the classes come to play.
24
25 //
26 // Scenario 1: Non CF url navigation through address bar (www.msn.com)
27 // - Bho::BeforeNavigate - top level url = www.msn.com
28 // - MSHTML -> MonikerPatch::BindToStorage.
29 //   (IEFrame starts this by calling mshtml!*SuperNavigate*)
30 //    - check if the url is a top level url
31 //    - iff the url is a top level url, we switch in our own callback object
32 //      and hook it up to the bind context (BSCBStorageBind)
33 //    - otherwise just call the original
34 // - BSCBStorageBind::OnDataAvailable - sniffs data and determines that the
35 //   renderer is not chrome. Goes into pass through mode.
36 // -  The page loads in mshtml.
37 //
38
39 //
40 // Scenario 2: CF navigation through address bar URL
41 // - Bho::BeforeNavigate - top level url = http://wave.google.com/
42 // - MSHTML -> MonikerPatch::BindToStorage.
43 //   (IEFrame starts this by calling mshtml!*SuperNavigate*)
44 //    - request_data is NULL
45 //    - check if the url is a top level url
46 //    - iff the url is a top level url, we switch in our own callback object
47 //      and hook it up to the bind context (BSCBStorageBind)
48 // - BSCBStorageBind::OnDataAvailable - sniffs data and determines that the
49 //   renderer is chrome. It then registers a special bind context param and
50 //   sets a magic clip format in the format_etc. Then goes into pass through
51 //   mode.
52 // - mshtml looks at the clip format and re-issues the navigation with the
53 //   same bind context. Also returns INET_E_TERMINATED_BIND so that same
54 //   underlying transaction objects are used.
55 // - IEFrame -> MonikerPatch::BindToStorage
56 //    - We check for the special bind context param and instantiate and
57 //      return our ActiveDoc
58
59 //
60 // Scenario 3: CF navigation through mshtml link
61 //  Same as scenario #2.
62 //
63
64 //
65 // Scenario 4: CF navigation through link click in chrome loads non CF page
66 // - Link click comes to ChromeActiveDocument::OnOpenURL
67 //    - web_browser->Navigate with URL
68 // - [Scenario 1]
69 //
70
71 //
72 // Scenario 5: CF navigation through link click in chrome loads CF page
73 // - Link click comes to ChromeActiveDocument::OnOpenURL
74 //    - web_browser->Navigate with URL
75 // - [Scenario 2]
76 //
77
78 // This class is the link between a few static, moniker related functions to
79 // the bho.  The specific services needed by those functions are abstracted into
80 // this interface for easier testability.
81 class NavigationManager {
82  public:
83   NavigationManager() {
84   }
85
86   // Returns the Bho instance for the current thread. This is returned from
87   // TLS.  Returns NULL if no instance exists on the current thread.
88   static NavigationManager* GetThreadInstance();
89
90   void RegisterThreadInstance();
91   void UnregisterThreadInstance();
92
93   virtual ~NavigationManager() {
94     DCHECK(GetThreadInstance() != this);
95   }
96
97   // Returns the url of the current top level navigation.
98   const std::wstring& url() const {
99     return url_;
100   }
101
102   // Called to set the current top level URL that's being navigated to.
103   void set_url(const wchar_t* url) {
104     DVLOG(1) << __FUNCTION__ << " " << url;
105     url_ = url;
106   }
107
108   // Returns the referrer header value of the current top level navigation.
109   const std::string& referrer() const {
110     return referrer_;
111   }
112
113   void set_referrer(const std::string& referrer) {
114     referrer_ = referrer;
115   }
116
117   // Return true if this is a URL that represents a top-level
118   // document that might have to be rendered in CF.
119   virtual bool IsTopLevelUrl(const wchar_t* url);
120
121   // Called when we've detected the http-equiv meta tag in the current page
122   // and need to switch over from mshtml to CF.
123   virtual HRESULT NavigateToCurrentUrlInCF(IBrowserService* browser);
124
125   void set_post_data(VARIANT* post_data) {
126     post_data_.Reset();
127     if (post_data) {
128       if (V_VT(post_data) == (VT_BYREF | VT_VARIANT)) {
129         post_data_.Set(*post_data->pvarVal);
130       } else {
131         NOTREACHED() << "unexpected type for post_data: "
132             << std::hex << post_data->vt;
133       }
134     }
135   }
136
137   const base::win::ScopedVariant& post_data() const {
138     return post_data_;
139   }
140
141   void set_headers(VARIANT* headers) {
142     headers_.Reset();
143     if (headers) {
144       headers_ = *headers;
145     }
146   }
147
148   const base::win::ScopedVariant& headers() const {
149     return headers_;
150   }
151
152  protected:
153   std::string referrer_;
154   std::wstring url_;
155   base::win::ScopedVariant post_data_;
156   base::win::ScopedVariant headers_;
157
158   static base::LazyInstance<base::ThreadLocalPointer<NavigationManager> >
159       thread_singleton_;
160
161  private:
162   DISALLOW_COPY_AND_ASSIGN(NavigationManager);
163 };
164
165 // static-only class that manages an IMoniker patch.
166 // We need this patch to stay in the loop when top-level HTML content is
167 // downloaded that might have the CF http-equiv meta tag.
168 // When we detect candidates for those requests, we add our own callback
169 // object (as explained at the top of this file) and use it to cache the
170 // original document contents in order to avoid multiple network trips
171 // if we need to switch the renderer over to CF.
172 class MonikerPatch {
173   MonikerPatch() {}  // no instances should be created of this class.
174  public:
175   // Patches two IMoniker methods, BindToObject and BindToStorage.
176   static bool Initialize();
177
178   // Nullifies the IMoniker patches.
179   static void Uninitialize();
180
181   // Typedefs for IMoniker methods.
182   typedef HRESULT (STDMETHODCALLTYPE* IMoniker_BindToObject_Fn)(IMoniker* me,
183       IBindCtx* bind_ctx, IMoniker* to_left, REFIID iid, void** obj);
184   typedef HRESULT (STDMETHODCALLTYPE* IMoniker_BindToStorage_Fn)(IMoniker* me,
185       IBindCtx* bind_ctx, IMoniker* to_left, REFIID iid, void** obj);
186
187   static STDMETHODIMP BindToObject(IMoniker_BindToObject_Fn original,
188                                    IMoniker* me, IBindCtx* bind_ctx,
189                                    IMoniker* to_left, REFIID iid, void** obj);
190
191   static STDMETHODIMP BindToStorage(IMoniker_BindToStorage_Fn original,
192                                     IMoniker* me, IBindCtx* bind_ctx,
193                                     IMoniker* to_left, REFIID iid, void** obj);
194 };
195
196 extern wchar_t* kChromeRequestParam;
197
198 #endif  // CHROME_FRAME_URLMON_MONIKER_H_