Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: chrome/browser/guest_view/web_view/web_view_permission_helper.cc

Issue 468323002: Introduce WebViewPermissionHelperDelegate. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/guest_view/web_view/web_view_permission_helper.h" 5 #include "chrome/browser/guest_view/web_view/web_view_permission_helper.h"
6 6
7 #include "chrome/browser/content_settings/tab_specific_content_settings.h" 7 #include "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_d elegate.h"
8 #include "chrome/browser/geolocation/geolocation_permission_context.h"
9 #include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
10 #include "chrome/browser/guest_view/web_view/web_view_constants.h" 8 #include "chrome/browser/guest_view/web_view/web_view_constants.h"
11 #include "chrome/browser/guest_view/web_view/web_view_guest.h" 9 #include "chrome/browser/guest_view/web_view/web_view_guest.h"
12 #include "chrome/browser/guest_view/web_view/web_view_permission_types.h" 10 #include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
13 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/render_messages.h"
16 #include "content/public/browser/render_process_host.h" 11 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/render_view_host.h" 12 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/user_metrics.h" 13 #include "content/public/browser/user_metrics.h"
14 #include "extensions/browser/guest_view/web_view/web_view_permission_helper_dele gate.h"
19 15
20 using content::BrowserPluginGuestDelegate; 16 using content::BrowserPluginGuestDelegate;
21 using content::RenderViewHost; 17 using content::RenderViewHost;
22 18
23 namespace extensions { 19 namespace extensions {
24 20
25 namespace { 21 namespace {
26 static std::string PermissionTypeToString(WebViewPermissionType type) { 22 static std::string PermissionTypeToString(WebViewPermissionType type) {
27 switch (type) { 23 switch (type) {
28 case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD: 24 case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 127 }
132 } 128 }
133 129
134 } // namespace 130 } // namespace
135 131
136 WebViewPermissionHelper::WebViewPermissionHelper(WebViewGuest* web_view_guest) 132 WebViewPermissionHelper::WebViewPermissionHelper(WebViewGuest* web_view_guest)
137 : content::WebContentsObserver(web_view_guest->guest_web_contents()), 133 : content::WebContentsObserver(web_view_guest->guest_web_contents()),
138 next_permission_request_id_(guestview::kInstanceIDNone), 134 next_permission_request_id_(guestview::kInstanceIDNone),
139 web_view_guest_(web_view_guest), 135 web_view_guest_(web_view_guest),
140 weak_factory_(this) { 136 weak_factory_(this) {
137 // TODO(hanxi) : Create the delegate through ExtensionsAPIClient after
138 // moving WebViewPermissionHelper to extensions.
139 web_view_permission_helper_delegate_.reset(
140 new ChromeWebViewPermissionHelperDelegate(this));
141 } 141 }
142 142
143 WebViewPermissionHelper::~WebViewPermissionHelper() { 143 WebViewPermissionHelper::~WebViewPermissionHelper() {
144 } 144 }
145 145
146 // static 146 // static
147 WebViewPermissionHelper* WebViewPermissionHelper::FromFrameID( 147 WebViewPermissionHelper* WebViewPermissionHelper::FromFrameID(
148 int render_process_id, 148 int render_process_id,
149 int render_frame_id) { 149 int render_frame_id) {
150 WebViewGuest* web_view_guest = WebViewGuest::FromFrameID( 150 WebViewGuest* web_view_guest = WebViewGuest::FromFrameID(
(...skipping 10 matching lines...) Expand all
161 WebViewGuest* web_view_guest = WebViewGuest::FromWebContents(web_contents); 161 WebViewGuest* web_view_guest = WebViewGuest::FromWebContents(web_contents);
162 if (!web_view_guest) 162 if (!web_view_guest)
163 return NULL; 163 return NULL;
164 return web_view_guest->web_view_permission_helper_.get(); 164 return web_view_guest->web_view_permission_helper_.get();
165 } 165 }
166 166
167 #if defined(ENABLE_PLUGINS) 167 #if defined(ENABLE_PLUGINS)
168 bool WebViewPermissionHelper::OnMessageReceived( 168 bool WebViewPermissionHelper::OnMessageReceived(
169 const IPC::Message& message, 169 const IPC::Message& message,
170 content::RenderFrameHost* render_frame_host) { 170 content::RenderFrameHost* render_frame_host) {
171 IPC_BEGIN_MESSAGE_MAP(WebViewPermissionHelper, message) 171 return web_view_permission_helper_delegate_->OnMessageReceived(
172 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedOutdatedPlugin, 172 message, render_frame_host);
173 OnBlockedOutdatedPlugin)
174 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedUnauthorizedPlugin,
175 OnBlockedUnauthorizedPlugin)
176 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NPAPINotSupported,
177 OnNPAPINotSupported)
178 #if defined(ENABLE_PLUGIN_INSTALLATION)
179 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FindMissingPlugin,
180 OnFindMissingPlugin)
181 #endif
182 IPC_MESSAGE_UNHANDLED(return false)
183 IPC_END_MESSAGE_MAP()
184
185 return true;
186 } 173 }
187 174
188 bool WebViewPermissionHelper::OnMessageReceived(const IPC::Message& message) { 175 bool WebViewPermissionHelper::OnMessageReceived(const IPC::Message& message) {
189 IPC_BEGIN_MESSAGE_MAP(WebViewPermissionHelper, message) 176 return web_view_permission_helper_delegate_->OnMessageReceived(message);
190 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CouldNotLoadPlugin,
191 OnCouldNotLoadPlugin)
192 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_OpenAboutPlugins,
193 OnOpenAboutPlugins)
194 #if defined(ENABLE_PLUGIN_INSTALLATION)
195 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemovePluginPlaceholderHost,
196 OnRemovePluginPlaceholderHost)
197 #endif
198 IPC_MESSAGE_UNHANDLED(return false)
199 IPC_END_MESSAGE_MAP()
200
201 return true;
202 } 177 }
203
204 void WebViewPermissionHelper::OnBlockedUnauthorizedPlugin(
205 const base::string16& name,
206 const std::string& identifier) {
207 const char kPluginName[] = "name";
208 const char kPluginIdentifier[] = "identifier";
209
210 base::DictionaryValue info;
211 info.SetString(std::string(kPluginName), name);
212 info.SetString(std::string(kPluginIdentifier), identifier);
213 RequestPermission(
214 WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN,
215 info,
216 base::Bind(&WebViewPermissionHelper::OnPermissionResponse,
217 weak_factory_.GetWeakPtr(),
218 identifier),
219 true /* allowed_by_default */);
220 content::RecordAction(
221 base::UserMetricsAction("WebView.Guest.PluginLoadRequest"));
222 }
223
224 void WebViewPermissionHelper::OnCouldNotLoadPlugin(
225 const base::FilePath& plugin_path) {
226 }
227
228 void WebViewPermissionHelper::OnBlockedOutdatedPlugin(
229 int placeholder_id,
230 const std::string& identifier) {
231 }
232
233 void WebViewPermissionHelper::OnNPAPINotSupported(const std::string& id) {
234 }
235
236 void WebViewPermissionHelper::OnOpenAboutPlugins() {
237 }
238
239 #if defined(ENABLE_PLUGIN_INSTALLATION)
240 void WebViewPermissionHelper::OnFindMissingPlugin(
241 int placeholder_id,
242 const std::string& mime_type) {
243 Send(new ChromeViewMsg_DidNotFindMissingPlugin(placeholder_id));
244 }
245
246 void WebViewPermissionHelper::OnRemovePluginPlaceholderHost(
247 int placeholder_id) {
248 }
249 #endif // defined(ENABLE_PLUGIN_INSTALLATION)
250
251 void WebViewPermissionHelper::OnPermissionResponse(
252 const std::string& identifier,
253 bool allow,
254 const std::string& input) {
255 if (allow) {
256 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
257 web_contents(), true, identifier);
258 }
259 }
260
261 #endif // defined(ENABLE_PLUGINS) 178 #endif // defined(ENABLE_PLUGINS)
262 179
263 void WebViewPermissionHelper::RequestMediaAccessPermission( 180 void WebViewPermissionHelper::RequestMediaAccessPermission(
264 content::WebContents* source, 181 content::WebContents* source,
265 const content::MediaStreamRequest& request, 182 const content::MediaStreamRequest& request,
266 const content::MediaResponseCallback& callback) { 183 const content::MediaResponseCallback& callback) {
267 base::DictionaryValue request_info; 184 web_view_permission_helper_delegate_-> RequestMediaAccessPermission(
268 request_info.SetString(guestview::kUrl, request.security_origin.spec()); 185 source, request, callback);
269 RequestPermission(WEB_VIEW_PERMISSION_TYPE_MEDIA,
270 request_info,
271 base::Bind(&WebViewPermissionHelper::
272 OnMediaPermissionResponse,
273 base::Unretained(this),
274 request,
275 callback),
276 false /* allowed_by_default */);
277 }
278
279 void WebViewPermissionHelper::OnMediaPermissionResponse(
280 const content::MediaStreamRequest& request,
281 const content::MediaResponseCallback& callback,
282 bool allow,
283 const std::string& user_input) {
284 if (!allow || !web_view_guest_->attached()) {
285 // Deny the request.
286 callback.Run(content::MediaStreamDevices(),
287 content::MEDIA_DEVICE_INVALID_STATE,
288 scoped_ptr<content::MediaStreamUI>());
289 return;
290 }
291 if (!web_view_guest_->embedder_web_contents()->GetDelegate())
292 return;
293
294 web_view_guest_->embedder_web_contents()->GetDelegate()->
295 RequestMediaAccessPermission(web_view_guest_->embedder_web_contents(),
296 request,
297 callback);
298 } 186 }
299 187
300 void WebViewPermissionHelper::CanDownload( 188 void WebViewPermissionHelper::CanDownload(
301 content::RenderViewHost* render_view_host, 189 content::RenderViewHost* render_view_host,
302 const GURL& url, 190 const GURL& url,
303 const std::string& request_method, 191 const std::string& request_method,
304 const base::Callback<void(bool)>& callback) { 192 const base::Callback<void(bool)>& callback) {
305 base::DictionaryValue request_info; 193 web_view_permission_helper_delegate_->CanDownload(
306 request_info.SetString(guestview::kUrl, url.spec()); 194 render_view_host, url, request_method, callback);
307 RequestPermission(
308 WEB_VIEW_PERMISSION_TYPE_DOWNLOAD,
309 request_info,
310 base::Bind(&WebViewPermissionHelper::OnDownloadPermissionResponse,
311 base::Unretained(this),
312 callback),
313 false /* allowed_by_default */);
314 }
315
316 void WebViewPermissionHelper::OnDownloadPermissionResponse(
317 const base::Callback<void(bool)>& callback,
318 bool allow,
319 const std::string& user_input) {
320 callback.Run(allow && web_view_guest_->attached());
321 } 195 }
322 196
323 void WebViewPermissionHelper::RequestPointerLockPermission( 197 void WebViewPermissionHelper::RequestPointerLockPermission(
324 bool user_gesture, 198 bool user_gesture,
325 bool last_unlocked_by_target, 199 bool last_unlocked_by_target,
326 const base::Callback<void(bool)>& callback) { 200 const base::Callback<void(bool)>& callback) {
327 base::DictionaryValue request_info; 201 web_view_permission_helper_delegate_->RequestPointerLockPermission(
328 request_info.SetBoolean(guestview::kUserGesture, user_gesture); 202 user_gesture, last_unlocked_by_target, callback);
329 request_info.SetBoolean(webview::kLastUnlockedBySelf,
330 last_unlocked_by_target);
331 request_info.SetString(guestview::kUrl,
332 web_contents()->GetLastCommittedURL().spec());
333
334 RequestPermission(
335 WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK,
336 request_info,
337 base::Bind(
338 &WebViewPermissionHelper::OnPointerLockPermissionResponse,
339 base::Unretained(this),
340 callback),
341 false /* allowed_by_default */);
342 }
343
344 void WebViewPermissionHelper::OnPointerLockPermissionResponse(
345 const base::Callback<void(bool)>& callback,
346 bool allow,
347 const std::string& user_input) {
348 callback.Run(allow && web_view_guest_->attached());
349 } 203 }
350 204
351 void WebViewPermissionHelper::RequestGeolocationPermission( 205 void WebViewPermissionHelper::RequestGeolocationPermission(
352 int bridge_id, 206 int bridge_id,
353 const GURL& requesting_frame, 207 const GURL& requesting_frame,
354 bool user_gesture, 208 bool user_gesture,
355 const base::Callback<void(bool)>& callback) { 209 const base::Callback<void(bool)>& callback) {
356 base::DictionaryValue request_info; 210 web_view_permission_helper_delegate_->RequestGeolocationPermission(
357 request_info.SetString(guestview::kUrl, requesting_frame.spec()); 211 bridge_id, requesting_frame, user_gesture, callback);
358 request_info.SetBoolean(guestview::kUserGesture, user_gesture);
359
360 // It is safe to hold an unretained pointer to WebViewPermissionHelper because
361 // this callback is called from WebViewPermissionHelper::SetPermission.
362 const PermissionResponseCallback permission_callback =
363 base::Bind(
364 &WebViewPermissionHelper::OnGeolocationPermissionResponse,
365 base::Unretained(this),
366 bridge_id,
367 user_gesture,
368 callback);
369 int request_id = RequestPermission(
370 WEB_VIEW_PERMISSION_TYPE_GEOLOCATION,
371 request_info,
372 permission_callback,
373 false /* allowed_by_default */);
374 bridge_id_to_request_id_map_[bridge_id] = request_id;
375 }
376
377 void WebViewPermissionHelper::OnGeolocationPermissionResponse(
378 int bridge_id,
379 bool user_gesture,
380 const base::Callback<void(bool)>& callback,
381 bool allow,
382 const std::string& user_input) {
383 // The <webview> embedder has allowed the permission. We now need to make sure
384 // that the embedder has geolocation permission.
385 RemoveBridgeID(bridge_id);
386
387 if (!allow || !web_view_guest_->attached()) {
388 callback.Run(false);
389 return;
390 }
391
392 Profile* profile = Profile::FromBrowserContext(
393 web_view_guest_->browser_context());
394 GeolocationPermissionContextFactory::GetForProfile(profile)->
395 RequestGeolocationPermission(
396 web_view_guest_->embedder_web_contents(),
397 // The geolocation permission request here is not initiated
398 // through WebGeolocationPermissionRequest. We are only interested
399 // in the fact whether the embedder/app has geolocation
400 // permission. Therefore we use an invalid |bridge_id|.
401 -1,
402 web_view_guest_->embedder_web_contents()->GetLastCommittedURL(),
403 user_gesture,
404 callback,
405 NULL);
406 } 212 }
407 213
408 void WebViewPermissionHelper::CancelGeolocationPermissionRequest( 214 void WebViewPermissionHelper::CancelGeolocationPermissionRequest(
409 int bridge_id) { 215 int bridge_id) {
410 int request_id = RemoveBridgeID(bridge_id); 216 web_view_permission_helper_delegate_->CancelGeolocationPermissionRequest(
411 RequestMap::iterator request_itr = 217 bridge_id);
412 pending_permission_requests_.find(request_id);
413
414 if (request_itr == pending_permission_requests_.end())
415 return;
416
417 pending_permission_requests_.erase(request_itr);
418 }
419
420 int WebViewPermissionHelper::RemoveBridgeID(int bridge_id) {
421 std::map<int, int>::iterator bridge_itr =
422 bridge_id_to_request_id_map_.find(bridge_id);
423 if (bridge_itr == bridge_id_to_request_id_map_.end())
424 return webview::kInvalidPermissionRequestID;
425
426 int request_id = bridge_itr->second;
427 bridge_id_to_request_id_map_.erase(bridge_itr);
428 return request_id;
429 } 218 }
430 219
431 void WebViewPermissionHelper::RequestFileSystemPermission( 220 void WebViewPermissionHelper::RequestFileSystemPermission(
432 const GURL& url, 221 const GURL& url,
433 bool allowed_by_default, 222 bool allowed_by_default,
434 const base::Callback<void(bool)>& callback) { 223 const base::Callback<void(bool)>& callback) {
435 base::DictionaryValue request_info; 224 web_view_permission_helper_delegate_->RequestFileSystemPermission(
436 request_info.SetString(guestview::kUrl, url.spec()); 225 url, allowed_by_default, callback);
437 RequestPermission(
438 WEB_VIEW_PERMISSION_TYPE_FILESYSTEM,
439 request_info,
440 base::Bind(
441 &WebViewPermissionHelper::OnFileSystemPermissionResponse,
442 base::Unretained(this),
443 callback),
444 allowed_by_default);
445 }
446
447 void WebViewPermissionHelper::OnFileSystemPermissionResponse(
448 const base::Callback<void(bool)>& callback,
449 bool allow,
450 const std::string& user_input) {
451 callback.Run(allow && web_view_guest_->attached());
452 } 226 }
453 227
454 void WebViewPermissionHelper::FileSystemAccessedAsync(int render_process_id, 228 void WebViewPermissionHelper::FileSystemAccessedAsync(int render_process_id,
455 int render_frame_id, 229 int render_frame_id,
456 int request_id, 230 int request_id,
457 const GURL& url, 231 const GURL& url,
458 bool blocked_by_policy) { 232 bool blocked_by_policy) {
459 RequestFileSystemPermission( 233 web_view_permission_helper_delegate_->FileSystemAccessedAsync(
460 url, 234 render_process_id, render_frame_id, request_id, url, blocked_by_policy);
461 !blocked_by_policy,
462 base::Bind(&WebViewPermissionHelper::FileSystemAccessedAsyncResponse,
463 base::Unretained(this),
464 render_process_id,
465 render_frame_id,
466 request_id,
467 url));
468 }
469
470 void WebViewPermissionHelper::FileSystemAccessedAsyncResponse(
471 int render_process_id,
472 int render_frame_id,
473 int request_id,
474 const GURL& url,
475 bool allowed) {
476 TabSpecificContentSettings::FileSystemAccessed(
477 render_process_id, render_frame_id, url, !allowed);
478 Send(new ChromeViewMsg_RequestFileSystemAccessAsyncResponse(
479 render_frame_id, request_id, allowed));
480 } 235 }
481 236
482 void WebViewPermissionHelper::FileSystemAccessedSync(int render_process_id, 237 void WebViewPermissionHelper::FileSystemAccessedSync(int render_process_id,
483 int render_frame_id, 238 int render_frame_id,
484 const GURL& url, 239 const GURL& url,
485 bool blocked_by_policy, 240 bool blocked_by_policy,
486 IPC::Message* reply_msg) { 241 IPC::Message* reply_msg) {
487 RequestFileSystemPermission( 242 web_view_permission_helper_delegate_->FileSystemAccessedSync(
488 url, 243 render_process_id, render_frame_id, url, blocked_by_policy, reply_msg);
489 !blocked_by_policy,
490 base::Bind(&WebViewPermissionHelper::FileSystemAccessedSyncResponse,
491 base::Unretained(this),
492 render_process_id,
493 render_frame_id,
494 url,
495 reply_msg));
496 }
497
498 void WebViewPermissionHelper::FileSystemAccessedSyncResponse(
499 int render_process_id,
500 int render_frame_id,
501 const GURL& url,
502 IPC::Message* reply_msg,
503 bool allowed) {
504 TabSpecificContentSettings::FileSystemAccessed(
505 render_process_id, render_frame_id, url, !allowed);
506 ChromeViewHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg,
507 allowed);
508 Send(reply_msg);
509 } 244 }
510 245
511 int WebViewPermissionHelper::RequestPermission( 246 int WebViewPermissionHelper::RequestPermission(
512 WebViewPermissionType permission_type, 247 WebViewPermissionType permission_type,
513 const base::DictionaryValue& request_info, 248 const base::DictionaryValue& request_info,
514 const PermissionResponseCallback& callback, 249 const PermissionResponseCallback& callback,
515 bool allowed_by_default) { 250 bool allowed_by_default) {
516 // If there are too many pending permission requests then reject this request. 251 // If there are too many pending permission requests then reject this request.
517 if (pending_permission_requests_.size() >= 252 if (pending_permission_requests_.size() >=
518 webview::kMaxOutstandingPermissionRequests) { 253 webview::kMaxOutstandingPermissionRequests) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 311
577 // Only record user initiated (i.e. non-default) actions. 312 // Only record user initiated (i.e. non-default) actions.
578 if (action != DEFAULT) 313 if (action != DEFAULT)
579 RecordUserInitiatedUMA(info, allow); 314 RecordUserInitiatedUMA(info, allow);
580 315
581 pending_permission_requests_.erase(request_itr); 316 pending_permission_requests_.erase(request_itr);
582 317
583 return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED; 318 return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED;
584 } 319 }
585 320
321 void WebViewPermissionHelper::CancelPendingPermissionRequest(int request_id) {
322 RequestMap::iterator request_itr =
323 pending_permission_requests_.find(request_id);
324
325 if (request_itr == pending_permission_requests_.end())
326 return;
327
328 pending_permission_requests_.erase(request_itr);
329 }
330
586 WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo() 331 WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo()
587 : permission_type(WEB_VIEW_PERMISSION_TYPE_UNKNOWN), 332 : permission_type(WEB_VIEW_PERMISSION_TYPE_UNKNOWN),
588 allowed_by_default(false) { 333 allowed_by_default(false) {
589 } 334 }
590 335
591 WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo( 336 WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo(
592 const PermissionResponseCallback& callback, 337 const PermissionResponseCallback& callback,
593 WebViewPermissionType permission_type, 338 WebViewPermissionType permission_type,
594 bool allowed_by_default) 339 bool allowed_by_default)
595 : callback(callback), 340 : callback(callback),
596 permission_type(permission_type), 341 permission_type(permission_type),
597 allowed_by_default(allowed_by_default) { 342 allowed_by_default(allowed_by_default) {
598 } 343 }
599 344
600 WebViewPermissionHelper::PermissionResponseInfo::~PermissionResponseInfo() { 345 WebViewPermissionHelper::PermissionResponseInfo::~PermissionResponseInfo() {
601 } 346 }
602 347
603 } // namespace extensions 348 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/guest_view/web_view/web_view_permission_helper.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698