1 // Copyright (c) 2012 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.
6 #include "secondary_tile.h"
8 #include <windows.ui.startscreen.h>
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/strings/utf_string_conversions.h"
14 #include "win8/metro_driver/chrome_app_view.h"
15 #include "win8/metro_driver/winrt_utils.h"
19 using base::win::MetroPinUmaResultCallback
;
21 // Callback for asynchronous pin requests.
22 class TileRequestCompleter
{
28 TileRequestCompleter(PinType type
, const MetroPinUmaResultCallback
& callback
)
29 : type_(type
), callback_(callback
) {}
31 void Complete(mswr::ComPtr
<winfoundtn::IAsyncOperation
<bool>>& completion
);
34 // Callback that responds to user input on the pin request pop-up. This will
35 // run |callback_|, then delete |this| before returning.
36 HRESULT
Respond(winfoundtn::IAsyncOperation
<bool>* async
,
40 MetroPinUmaResultCallback callback_
;
43 void TileRequestCompleter::Complete(
44 mswr::ComPtr
<winfoundtn::IAsyncOperation
<bool>>& completion
) {
45 typedef winfoundtn::IAsyncOperationCompletedHandler
<bool> RequestDoneType
;
46 mswr::ComPtr
<RequestDoneType
> handler(mswr::Callback
<RequestDoneType
>(
47 this, &TileRequestCompleter::Respond
));
48 DCHECK(handler
.Get() != NULL
);
49 HRESULT hr
= completion
->put_Completed(handler
.Get());
50 CheckHR(hr
, "Failed to put_Completed");
53 HRESULT
TileRequestCompleter::Respond(winfoundtn::IAsyncOperation
<bool>* async
,
55 base::win::MetroSecondaryTilePinUmaResult pin_state
=
56 base::win::METRO_PIN_STATE_NONE
;
58 if (status
== Completed
) {
60 CheckHR(async
->GetResults(&result
));
61 LOG(INFO
) << __FUNCTION__
<< " result " << static_cast<int>(result
);
64 pin_state
= type_
== PIN
?
65 base::win::METRO_PIN_RESULT_CANCEL
:
66 base::win::METRO_UNPIN_RESULT_CANCEL
;
69 pin_state
= type_
== PIN
?
70 base::win::METRO_PIN_RESULT_OK
:
71 base::win::METRO_UNPIN_RESULT_OK
;
74 pin_state
= type_
== PIN
?
75 base::win::METRO_PIN_RESULT_OTHER
:
76 base::win::METRO_UNPIN_RESULT_OTHER
;
80 LOG(ERROR
) << __FUNCTION__
<< " Unexpected async status "
81 << static_cast<int>(status
);
82 pin_state
= type_
== PIN
?
83 base::win::METRO_PIN_RESULT_ERROR
:
84 base::win::METRO_UNPIN_RESULT_ERROR
;
86 callback_
.Run(pin_state
);
92 void DeleteTileFromStartScreen(const string16
& tile_id
,
93 const MetroPinUmaResultCallback
& callback
) {
94 DVLOG(1) << __FUNCTION__
;
95 mswr::ComPtr
<winui::StartScreen::ISecondaryTileFactory
> tile_factory
;
96 HRESULT hr
= winrt_utils::CreateActivationFactory(
97 RuntimeClass_Windows_UI_StartScreen_SecondaryTile
,
98 tile_factory
.GetAddressOf());
99 CheckHR(hr
, "Failed to create instance of ISecondaryTileFactory");
102 id
.Attach(MakeHString(tile_id
));
104 mswr::ComPtr
<winui::StartScreen::ISecondaryTile
> tile
;
105 hr
= tile_factory
->CreateWithId(id
.Get(), tile
.GetAddressOf());
106 CheckHR(hr
, "Failed to create tile");
108 mswr::ComPtr
<winfoundtn::IAsyncOperation
<bool>> completion
;
109 hr
= tile
->RequestDeleteAsync(completion
.GetAddressOf());
110 CheckHR(hr
, "RequestDeleteAsync failed");
113 callback
.Run(base::win::METRO_UNPIN_REQUEST_SHOW_ERROR
);
117 // Deleted in TileRequestCompleter::Respond when the async operation
119 TileRequestCompleter
* completer
=
120 new TileRequestCompleter(TileRequestCompleter::UNPIN
, callback
);
121 completer
->Complete(completion
);
124 void CreateTileOnStartScreen(const string16
& tile_id
,
125 const string16
& title_str
,
126 const string16
& url_str
,
127 const base::FilePath
& logo_path
,
128 const MetroPinUmaResultCallback
& callback
) {
129 VLOG(1) << __FUNCTION__
;
131 mswr::ComPtr
<winui::StartScreen::ISecondaryTileFactory
> tile_factory
;
132 HRESULT hr
= winrt_utils::CreateActivationFactory(
133 RuntimeClass_Windows_UI_StartScreen_SecondaryTile
,
134 tile_factory
.GetAddressOf());
135 CheckHR(hr
, "Failed to create instance of ISecondaryTileFactory");
137 winui::StartScreen::TileOptions options
=
138 winui::StartScreen::TileOptions_ShowNameOnLogo
;
139 mswrw::HString title
;
140 title
.Attach(MakeHString(title_str
));
143 id
.Attach(MakeHString(tile_id
));
146 // The url is just passed into the tile agruments as is. Metro and desktop
147 // chrome will see the arguments as command line parameters.
148 // A GURL is used to ensure any spaces are properly escaped.
150 args
.Attach(MakeHString(UTF8ToUTF16(url
.spec())));
152 mswr::ComPtr
<winfoundtn::IUriRuntimeClassFactory
> uri_factory
;
153 hr
= winrt_utils::CreateActivationFactory(
154 RuntimeClass_Windows_Foundation_Uri
,
155 uri_factory
.GetAddressOf());
156 CheckHR(hr
, "Failed to create URIFactory");
158 mswrw::HString logo_url
;
159 logo_url
.Attach(MakeHString(string16(L
"file:///").append(logo_path
.value())));
160 mswr::ComPtr
<winfoundtn::IUriRuntimeClass
> uri
;
161 hr
= uri_factory
->CreateUri(logo_url
.Get(), &uri
);
162 CheckHR(hr
, "Failed to create URI");
164 mswr::ComPtr
<winui::StartScreen::ISecondaryTile
> tile
;
165 hr
= tile_factory
->CreateTile(id
.Get(),
171 tile
.GetAddressOf());
172 CheckHR(hr
, "Failed to create tile");
174 hr
= tile
->put_ForegroundText(winui::StartScreen::ForegroundText_Light
);
175 CheckHR(hr
, "Failed to change foreground text color");
177 mswr::ComPtr
<winfoundtn::IAsyncOperation
<bool>> completion
;
178 hr
= tile
->RequestCreateAsync(completion
.GetAddressOf());
179 CheckHR(hr
, "RequestCreateAsync failed");
182 callback
.Run(base::win::METRO_PIN_REQUEST_SHOW_ERROR
);
186 // Deleted in TileRequestCompleter::Respond when the async operation
188 TileRequestCompleter
* completer
=
189 new TileRequestCompleter(TileRequestCompleter::PIN
, callback
);
190 completer
->Complete(completion
);
195 BOOL
MetroIsPinnedToStartScreen(const string16
& tile_id
) {
196 mswr::ComPtr
<winui::StartScreen::ISecondaryTileStatics
> tile_statics
;
197 HRESULT hr
= winrt_utils::CreateActivationFactory(
198 RuntimeClass_Windows_UI_StartScreen_SecondaryTile
,
199 tile_statics
.GetAddressOf());
200 CheckHR(hr
, "Failed to create instance of ISecondaryTileStatics");
203 hr
= tile_statics
->Exists(MakeHString(tile_id
), &exists
);
204 CheckHR(hr
, "ISecondaryTileStatics.Exists failed");
208 void MetroUnPinFromStartScreen(const string16
& tile_id
,
209 const MetroPinUmaResultCallback
& callback
) {
210 globals
.appview_msg_loop
->PostTask(
211 FROM_HERE
, base::Bind(&DeleteTileFromStartScreen
,
216 void MetroPinToStartScreen(const string16
& tile_id
,
217 const string16
& title
,
219 const base::FilePath
& logo_path
,
220 const MetroPinUmaResultCallback
& callback
) {
221 globals
.appview_msg_loop
->PostTask(
222 FROM_HERE
, base::Bind(&CreateTileOnStartScreen
,