[Author: aa]
[google-gears.git] / gears / factory / ie / factory.cc
blob20457c7bb3c8330d9baf3cf804617912e4bffce5
1 // Copyright 2006, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <assert.h>
28 #include "gears/base/common/string16.h"
29 #include "gears/base/ie/activex_utils.h"
30 #include "gears/base/ie/atl_headers.h"
31 #include "gears/base/ie/detect_version_collision.h"
32 #include "gears/console/ie/console_ie.h"
33 #include "gears/database/ie/database.h"
34 #include "gears/desktop/desktop_ie.h"
35 #include "gears/factory/common/factory_utils.h"
36 #include "gears/factory/ie/factory.h"
37 #include "gears/httprequest/ie/httprequest_ie.h"
38 #include "gears/localserver/ie/localserver_ie.h"
39 #include "gears/timer/timer.h"
40 #include "gears/workerpool/ie/workerpool.h"
42 #ifdef DEBUG
43 #include "gears/cctests/test_ie.h"
44 #endif
47 GearsFactory::GearsFactory()
48 : is_creation_suspended_(false),
49 is_permission_granted_(false),
50 is_permission_value_from_user_(false) {
51 SetActiveUserFlag();
55 STDMETHODIMP GearsFactory::create(const BSTR object_name_bstr_in,
56 const VARIANT *version_variant,
57 IDispatch **retval) {
58 HRESULT hr;
60 const BSTR object_name_bstr = ActiveXUtils::SafeBSTR(object_name_bstr_in);
62 LOG16((L"GearsFactory::create(%s)\n", object_name_bstr));
64 if (DetectedVersionCollision()) {
65 if (!EnvIsWorker()) {
66 MaybeNotifyUserOfVersionCollision(); // only notifies once per process
68 RETURN_EXCEPTION(kVersionCollisionErrorMessage);
71 // Make sure the user gives this origin permission to use Gears.
73 if (!HasPermissionToUseGears(this, NULL, NULL, NULL)) {
74 RETURN_EXCEPTION(STRING16(L"Page does not have permission to use "
75 PRODUCT_FRIENDLY_NAME L"."));
78 // Check the version string.
80 std::string16 version;
81 if (!ActiveXUtils::OptionalVariantIsPresent(version_variant)) {
82 version = STRING16(L"1.0"); // default value for this optional param
83 } else {
84 if (version_variant->vt != VT_BSTR) {
85 RETURN_EXCEPTION(STRING16(L"Invalid parameter."));
87 version = version_variant->bstrVal;
90 if (version != kAllowedClassVersion) {
91 RETURN_EXCEPTION(STRING16(L"Invalid version string. Must be 1.0."));
94 // Create an instance of the object.
96 // Do case-sensitive comparisons, which are always better in APIs. They make
97 // code consistent across callers, and they are easier to support over time.
99 std::string16 object_name(object_name_bstr);
100 ModuleImplBaseClass *base_class = NULL;
101 CComQIPtr<IDispatch> idispatch;
103 hr = E_FAIL;
104 if (0) { // dummy statement to support mixed "#ifdef" and "else if" below
105 #ifdef WINCE
106 // TODO(oshlack): Implement console for WinCE.
107 #else
108 } else if (object_name == STRING16(L"beta.console")) {
109 CComObject<GearsConsole> *obj;
110 hr = CComObject<GearsConsole>::CreateInstance(&obj);
111 base_class = obj;
112 idispatch = obj;
113 #endif
114 } else if (object_name == STRING16(L"beta.database")) {
115 CComObject<GearsDatabase> *obj;
116 hr = CComObject<GearsDatabase>::CreateInstance(&obj);
117 base_class = obj;
118 idispatch = obj;
119 #ifdef WINCE
120 // TODO(steveblock): Implement desktop for WinCE.
121 #else
122 } else if (object_name == STRING16(L"beta.desktop")) {
123 CComObject<GearsDesktop> *obj;
124 hr = CComObject<GearsDesktop>::CreateInstance(&obj);
125 base_class = obj;
126 idispatch = obj;
127 #endif
128 } else if (object_name == STRING16(L"beta.httprequest")) {
129 CComObject<GearsHttpRequest> *obj;
130 hr = CComObject<GearsHttpRequest>::CreateInstance(&obj);
131 base_class = obj;
132 idispatch = obj;
133 } else if (object_name == STRING16(L"beta.localserver")) {
134 CComObject<GearsLocalServer> *obj;
135 hr = CComObject<GearsLocalServer>::CreateInstance(&obj);
136 base_class = obj;
137 idispatch = obj;
138 } else if (object_name == STRING16(L"beta.test")) {
139 #ifdef DEBUG
140 CComObject<GearsTest> *obj;
141 hr = CComObject<GearsTest>::CreateInstance(&obj);
142 base_class = obj;
143 idispatch = obj;
144 #else
145 RETURN_EXCEPTION(STRING16(L"Object is only available in debug build."));
146 #endif
147 } else if (object_name == STRING16(L"beta.timer")) {
148 CComObject<GearsTimer> *obj;
149 hr = CComObject<GearsTimer>::CreateInstance(&obj);
150 base_class = obj;
151 idispatch = obj;
152 } else if (object_name == STRING16(L"beta.workerpool")) {
153 CComObject<GearsWorkerPool> *obj;
154 hr = CComObject<GearsWorkerPool>::CreateInstance(&obj);
155 base_class = obj;
156 idispatch = obj;
157 } else {
158 RETURN_EXCEPTION(STRING16(L"Unknown object."));
161 if (FAILED(hr) || !base_class || !idispatch) {
162 RETURN_EXCEPTION(STRING16(L"Failed to create requested object."));
165 // setup the ModuleImplBaseClass (copy settings from this factory)
166 if (!base_class->InitBaseFromSibling(this)) {
167 RETURN_EXCEPTION(STRING16(L"Error initializing base class."));
170 // Our factory-created Gears objects no longer need to be sited, since we get
171 // the domain and location_url from ModuleImplBaseClass. But we may someday
172 // later need an object to be sited, in which case we should enable this code.
174 //// SetSite any object that supports IObjectWithSite
175 //if (SUCCEEDED(hr)) {
176 // CComQIPtr<IObjectWithSite> object_with_site = idispatch;
177 // if (object_with_site) {
178 // hr = object_with_site->SetSite(m_spUnkSite);
179 // }
182 *retval = idispatch;
183 (*retval)->AddRef(); // ~CComQIPtr will Release, so must AddRef here
184 assert((*retval)->AddRef() == 3 &&
185 (*retval)->Release() == 2);
186 RETURN_NORMAL();
190 STDMETHODIMP GearsFactory::getBuildInfo(BSTR *retval) {
191 LOG16((L"GearsFactory::getBuildInfo()\n"));
192 std::string16 build_info;
193 AppendBuildInfo(&build_info);
194 if (DetectedVersionCollision()) {
195 build_info += L" (pending browser restart)";
198 *retval = SysAllocString(build_info.c_str());
199 if (*retval == NULL) {
200 RETURN_EXCEPTION(STRING16(L"Internal error."));
202 RETURN_NORMAL();
206 STDMETHODIMP GearsFactory::get_version(BSTR *retval) {
207 *retval = SysAllocString(STRING16(PRODUCT_VERSION_STRING));
208 if (*retval == NULL) {
209 RETURN_EXCEPTION(STRING16(L"Internal error."));
211 RETURN_NORMAL();
215 #ifdef WINCE
216 // Hold WinCE feature set at version 0.2 for now.
217 #else
218 STDMETHODIMP GearsFactory::getPermission(const BSTR site_name_in,
219 const BSTR image_url_in,
220 const BSTR extra_message_in,
221 VARIANT_BOOL *retval) {
222 // Guard against NULL BSTRs.
223 // TODO(cprince): Do this automatically in JsParamFetcher for IE.
224 const BSTR site_name = ActiveXUtils::SafeBSTR(site_name_in);
225 const BSTR image_url = ActiveXUtils::SafeBSTR(image_url_in);
226 const BSTR extra_message = ActiveXUtils::SafeBSTR(extra_message_in);
228 if (HasPermissionToUseGears(this, image_url,
229 site_name, extra_message)) {
230 *retval = VARIANT_TRUE;
231 } else {
232 *retval = VARIANT_FALSE;
234 RETURN_NORMAL();
238 // Purposely ignores 'is_creation_suspended_'. The 'hasPermission' property
239 // indicates whether USER opt-in is still required, not whether DEVELOPER
240 // methods have been called correctly (e.g. allowCrossOrigin).
241 STDMETHODIMP GearsFactory::get_hasPermission(VARIANT_BOOL *retval) {
242 *retval = is_permission_granted_ ? VARIANT_TRUE : VARIANT_FALSE;
243 RETURN_NORMAL();
245 #endif
248 // InitBaseFromDOM needs the object to be sited. We override SetSite just to
249 // know when this happens, so we can do some one-time setup afterward.
250 STDMETHODIMP GearsFactory::SetSite(IUnknown *site) {
251 HRESULT hr = IObjectWithSiteImpl<GearsFactory>::SetSite(site);
252 #ifdef WINCE
253 // We are unable to get IWebBrowser2 from this pointer. Instead, the user must
254 // call privateSetGlobalObject from JavaScript.
255 #else
256 InitBaseFromDOM(m_spUnkSite);
257 #endif
258 return hr;
261 #ifdef WINCE
262 STDMETHODIMP GearsFactory::privateSetGlobalObject(IDispatch *js_dispatch) {
263 return InitBaseFromDOM(js_dispatch);
265 #endif
267 // TODO(cprince): See if we can use Suspend/Resume with the opt-in dialog too,
268 // rather than just the cross-origin worker case. (Code re-use == good.)
269 void GearsFactory::SuspendObjectCreation() {
270 is_creation_suspended_ = true;
273 void GearsFactory::ResumeObjectCreationAndUpdatePermissions() {
274 // TODO(cprince): The transition from suspended to resumed is where we should
275 // propagate cross-origin opt-in to the permissions DB.
276 is_creation_suspended_ = false;