1 // Copyright 2006, Google Inc.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
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.
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"
43 #include "gears/cctests/test_ie.h"
47 GearsFactory::GearsFactory()
48 : is_creation_suspended_(false),
49 is_permission_granted_(false),
50 is_permission_value_from_user_(false) {
55 STDMETHODIMP
GearsFactory::create(const BSTR object_name_bstr_in
,
56 const VARIANT
*version_variant
,
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()) {
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
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
;
104 if (0) { // dummy statement to support mixed "#ifdef" and "else if" below
106 // TODO(oshlack): Implement console for WinCE.
108 } else if (object_name
== STRING16(L
"beta.console")) {
109 CComObject
<GearsConsole
> *obj
;
110 hr
= CComObject
<GearsConsole
>::CreateInstance(&obj
);
114 } else if (object_name
== STRING16(L
"beta.database")) {
115 CComObject
<GearsDatabase
> *obj
;
116 hr
= CComObject
<GearsDatabase
>::CreateInstance(&obj
);
120 // TODO(steveblock): Implement desktop for WinCE.
122 } else if (object_name
== STRING16(L
"beta.desktop")) {
123 CComObject
<GearsDesktop
> *obj
;
124 hr
= CComObject
<GearsDesktop
>::CreateInstance(&obj
);
128 } else if (object_name
== STRING16(L
"beta.httprequest")) {
129 CComObject
<GearsHttpRequest
> *obj
;
130 hr
= CComObject
<GearsHttpRequest
>::CreateInstance(&obj
);
133 } else if (object_name
== STRING16(L
"beta.localserver")) {
134 CComObject
<GearsLocalServer
> *obj
;
135 hr
= CComObject
<GearsLocalServer
>::CreateInstance(&obj
);
138 } else if (object_name
== STRING16(L
"beta.test")) {
140 CComObject
<GearsTest
> *obj
;
141 hr
= CComObject
<GearsTest
>::CreateInstance(&obj
);
145 RETURN_EXCEPTION(STRING16(L
"Object is only available in debug build."));
147 } else if (object_name
== STRING16(L
"beta.timer")) {
148 CComObject
<GearsTimer
> *obj
;
149 hr
= CComObject
<GearsTimer
>::CreateInstance(&obj
);
152 } else if (object_name
== STRING16(L
"beta.workerpool")) {
153 CComObject
<GearsWorkerPool
> *obj
;
154 hr
= CComObject
<GearsWorkerPool
>::CreateInstance(&obj
);
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);
183 (*retval
)->AddRef(); // ~CComQIPtr will Release, so must AddRef here
184 assert((*retval
)->AddRef() == 3 &&
185 (*retval
)->Release() == 2);
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."));
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."));
216 // Hold WinCE feature set at version 0.2 for now.
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
;
232 *retval
= VARIANT_FALSE
;
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
;
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
);
253 // We are unable to get IWebBrowser2 from this pointer. Instead, the user must
254 // call privateSetGlobalObject from JavaScript.
256 InitBaseFromDOM(m_spUnkSite
);
262 STDMETHODIMP
GearsFactory::privateSetGlobalObject(IDispatch
*js_dispatch
) {
263 return InitBaseFromDOM(js_dispatch
);
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;