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

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

Issue 336283002: Remove GuestWebContentsCreated (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@simplify_creation
Patch Set: Fixed lifetime Created 6 years, 6 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_guest.h" 5 #include "chrome/browser/guest_view/web_view/web_view_guest.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/chrome_notification_types.h"
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 #if defined(ENABLE_FULL_PRINTING) 177 #if defined(ENABLE_FULL_PRINTING)
178 printing::PrintViewManager::CreateForWebContents(contents); 178 printing::PrintViewManager::CreateForWebContents(contents);
179 printing::PrintPreviewMessageHandler::CreateForWebContents(contents); 179 printing::PrintPreviewMessageHandler::CreateForWebContents(contents);
180 #else 180 #else
181 printing::PrintViewManagerBasic::CreateForWebContents(contents); 181 printing::PrintViewManagerBasic::CreateForWebContents(contents);
182 #endif // defined(ENABLE_FULL_PRINTING) 182 #endif // defined(ENABLE_FULL_PRINTING)
183 #endif // defined(ENABLE_PRINTING) 183 #endif // defined(ENABLE_PRINTING)
184 PDFTabHelper::CreateForWebContents(contents); 184 PDFTabHelper::CreateForWebContents(contents);
185 } 185 }
186 186
187 void ParsePartitionParam(const base::DictionaryValue& create_params,
188 std::string* storage_partition_id,
189 bool* persist_storage) {
190 std::string partition_str;
191 if (!create_params.GetString(webview::kStoragePartitionId, &partition_str)) {
192 return;
193 }
194
195 // Since the "persist:" prefix is in ASCII, StartsWith will work fine on
196 // UTF-8 encoded |partition_id|. If the prefix is a match, we can safely
197 // remove the prefix without splicing in the middle of a multi-byte codepoint.
198 // We can use the rest of the string as UTF-8 encoded one.
199 if (StartsWithASCII(partition_str, "persist:", true)) {
200 size_t index = partition_str.find(":");
201 CHECK(index != std::string::npos);
202 // It is safe to do index + 1, since we tested for the full prefix above.
203 *storage_partition_id = partition_str.substr(index + 1);
204
205 if (storage_partition_id->empty()) {
206 // TODO(lazyboy): Better way to deal with this error.
207 return;
208 }
209 *persist_storage = true;
210 } else {
211 *storage_partition_id = partition_str;
212 *persist_storage = false;
213 }
214 }
215
216
187 } // namespace 217 } // namespace
188 218
189 WebViewGuest::WebViewGuest(int guest_instance_id, 219 WebViewGuest::WebViewGuest(int guest_instance_id)
190 WebContents* guest_web_contents,
191 const std::string& embedder_extension_id)
192 : GuestView<WebViewGuest>(guest_instance_id), 220 : GuestView<WebViewGuest>(guest_instance_id),
193 script_executor_(new extensions::ScriptExecutor(guest_web_contents,
194 &script_observers_)),
195 pending_context_menu_request_id_(0), 221 pending_context_menu_request_id_(0),
196 next_permission_request_id_(0), 222 next_permission_request_id_(0),
197 is_overriding_user_agent_(false), 223 is_overriding_user_agent_(false),
198 main_frame_id_(0), 224 main_frame_id_(0),
199 chromevox_injected_(false), 225 chromevox_injected_(false),
200 find_helper_(this), 226 find_helper_(this),
201 javascript_dialog_helper_(this) { 227 javascript_dialog_helper_(this) {
202 Init(guest_web_contents, embedder_extension_id);
203 notification_registrar_.Add(
204 this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
205 content::Source<WebContents>(guest_web_contents));
206
207 notification_registrar_.Add(
208 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
209 content::Source<WebContents>(guest_web_contents));
210
211 #if defined(OS_CHROMEOS)
212 chromeos::AccessibilityManager* accessibility_manager =
213 chromeos::AccessibilityManager::Get();
214 CHECK(accessibility_manager);
215 accessibility_subscription_ = accessibility_manager->RegisterCallback(
216 base::Bind(&WebViewGuest::OnAccessibilityStatusChanged,
217 base::Unretained(this)));
218 #endif
219
220 AttachWebViewHelpers(guest_web_contents);
221 } 228 }
222 229
223 // static 230 // static
224 bool WebViewGuest::GetGuestPartitionConfigForSite( 231 bool WebViewGuest::GetGuestPartitionConfigForSite(
225 const GURL& site, 232 const GURL& site,
226 std::string* partition_domain, 233 std::string* partition_domain,
227 std::string* partition_name, 234 std::string* partition_name,
228 bool* in_memory) { 235 bool* in_memory) {
229 if (!site.SchemeIs(content::kGuestScheme)) 236 if (!site.SchemeIs(content::kGuestScheme))
230 return false; 237 return false;
(...skipping 18 matching lines...) Expand all
249 // static 256 // static
250 int WebViewGuest::GetViewInstanceId(WebContents* contents) { 257 int WebViewGuest::GetViewInstanceId(WebContents* contents) {
251 WebViewGuest* guest = FromWebContents(contents); 258 WebViewGuest* guest = FromWebContents(contents);
252 if (!guest) 259 if (!guest)
253 return guestview::kInstanceIDNone; 260 return guestview::kInstanceIDNone;
254 261
255 return guest->view_instance_id(); 262 return guest->view_instance_id();
256 } 263 }
257 264
258 // static 265 // static
259 void WebViewGuest::ParsePartitionParam(
260 const base::DictionaryValue* extra_params,
261 std::string* storage_partition_id,
262 bool* persist_storage) {
263 std::string partition_str;
264 if (!extra_params->GetString(webview::kStoragePartitionId, &partition_str)) {
265 return;
266 }
267
268 // Since the "persist:" prefix is in ASCII, StartsWith will work fine on
269 // UTF-8 encoded |partition_id|. If the prefix is a match, we can safely
270 // remove the prefix without splicing in the middle of a multi-byte codepoint.
271 // We can use the rest of the string as UTF-8 encoded one.
272 if (StartsWithASCII(partition_str, "persist:", true)) {
273 size_t index = partition_str.find(":");
274 CHECK(index != std::string::npos);
275 // It is safe to do index + 1, since we tested for the full prefix above.
276 *storage_partition_id = partition_str.substr(index + 1);
277
278 if (storage_partition_id->empty()) {
279 // TODO(lazyboy): Better way to deal with this error.
280 return;
281 }
282 *persist_storage = true;
283 } else {
284 *storage_partition_id = partition_str;
285 *persist_storage = false;
286 }
287 }
288
289 // static
290 void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info, 266 void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info,
291 bool allow) { 267 bool allow) {
292 if (allow) { 268 if (allow) {
293 // Note that |allow| == true means the embedder explicitly allowed the 269 // Note that |allow| == true means the embedder explicitly allowed the
294 // request. For some requests they might still fail. An example of such 270 // request. For some requests they might still fail. An example of such
295 // scenario would be: an embedder allows geolocation request but doesn't 271 // scenario would be: an embedder allows geolocation request but doesn't
296 // have geolocation access on its own. 272 // have geolocation access on its own.
297 switch (info.permission_type) { 273 switch (info.permission_type) {
298 case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD: 274 case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
299 content::RecordAction( 275 content::RecordAction(
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 // TODO(lazyboy): We need to expose some kind of enum equivalent of 354 // TODO(lazyboy): We need to expose some kind of enum equivalent of
379 // |command_id| instead of plain integers. 355 // |command_id| instead of plain integers.
380 item_value->SetInteger(webview::kMenuItemCommandId, 356 item_value->SetInteger(webview::kMenuItemCommandId,
381 menu_model.GetCommandIdAt(i)); 357 menu_model.GetCommandIdAt(i));
382 item_value->SetString(webview::kMenuItemLabel, menu_model.GetLabelAt(i)); 358 item_value->SetString(webview::kMenuItemLabel, menu_model.GetLabelAt(i));
383 items->Append(item_value); 359 items->Append(item_value);
384 } 360 }
385 return items.Pass(); 361 return items.Pass();
386 } 362 }
387 363
364 void WebViewGuest::CreateWebContents(
365 const std::string& embedder_extension_id,
366 content::RenderProcessHost* embedder_render_process_host,
367 const base::DictionaryValue& create_params,
368 const WebContentsCallback& callback) {
369 std::string storage_partition_id;
370 bool persist_storage = false;
371 std::string storage_partition_string;
372 ParsePartitionParam(create_params, &storage_partition_id, &persist_storage);
373 // Validate that the partition id coming from the renderer is valid UTF-8,
374 // since we depend on this in other parts of the code, such as FilePath
375 // creation. If the validation fails, treat it as a bad message and kill the
376 // renderer process.
377 if (!base::IsStringUTF8(storage_partition_id)) {
378 content::RecordAction(
379 base::UserMetricsAction("BadMessageTerminate_BPGM"));
380 base::KillProcess(
381 embedder_render_process_host->GetHandle(),
382 content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
383 return;
384 }
385 std::string url_encoded_partition = net::EscapeQueryParamValue(
386 storage_partition_id, false);
387 // The SiteInstance of a given webview tag is based on the fact that it's
388 // a guest process in addition to which platform application the tag
389 // belongs to and what storage partition is in use, rather than the URL
390 // that the tag is being navigated to.
391 GURL guest_site(base::StringPrintf("%s://%s/%s?%s",
392 content::kGuestScheme,
393 embedder_extension_id.c_str(),
394 persist_storage ? "persist" : "",
395 url_encoded_partition.c_str()));
396
397 // If we already have a webview tag in the same app using the same storage
398 // partition, we should use the same SiteInstance so the existing tag and
399 // the new tag can script each other.
400 GuestViewManager* guest_view_manager =
401 GuestViewManager::FromBrowserContext(
402 embedder_render_process_host->GetBrowserContext());
403 content::SiteInstance* guest_site_instance =
404 guest_view_manager->GetGuestSiteInstance(guest_site);
405 if (!guest_site_instance) {
406 // Create the SiteInstance in a new BrowsingInstance, which will ensure
407 // that webview tags are also not allowed to send messages across
408 // different partitions.
409 guest_site_instance = content::SiteInstance::CreateForURL(
410 embedder_render_process_host->GetBrowserContext(), guest_site);
411 }
412 WebContents::CreateParams params(
413 embedder_render_process_host->GetBrowserContext(),
414 guest_site_instance);
415 params.guest_delegate = this;
416 callback.Run(WebContents::Create(params));
417 }
418
388 void WebViewGuest::DidAttach() { 419 void WebViewGuest::DidAttach() {
389 AddWebViewToExtensionRendererState(); 420 AddWebViewToExtensionRendererState();
390 421
391 std::string name; 422 std::string name;
392 if (extra_params()->GetString(webview::kName, &name)) { 423 if (extra_params()->GetString(webview::kName, &name)) {
393 // If the guest window's name is empty, then the WebView tag's name is 424 // If the guest window's name is empty, then the WebView tag's name is
394 // assigned. Otherwise, the guest window's name takes precedence over the 425 // assigned. Otherwise, the guest window's name takes precedence over the
395 // WebView tag's name. 426 // WebView tag's name.
396 if (name_.empty()) 427 if (name_.empty())
397 name_ = name; 428 name_ = name;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 void WebViewGuest::GuestDestroyed() { 487 void WebViewGuest::GuestDestroyed() {
457 // Clean up custom context menu items for this guest. 488 // Clean up custom context menu items for this guest.
458 extensions::MenuManager* menu_manager = extensions::MenuManager::Get( 489 extensions::MenuManager* menu_manager = extensions::MenuManager::Get(
459 Profile::FromBrowserContext(browser_context())); 490 Profile::FromBrowserContext(browser_context()));
460 menu_manager->RemoveAllContextItems(extensions::MenuItem::ExtensionKey( 491 menu_manager->RemoveAllContextItems(extensions::MenuItem::ExtensionKey(
461 embedder_extension_id(), view_instance_id())); 492 embedder_extension_id(), view_instance_id()));
462 493
463 RemoveWebViewFromExtensionRendererState(web_contents()); 494 RemoveWebViewFromExtensionRendererState(web_contents());
464 } 495 }
465 496
497 void WebViewGuest::Init() {
498 script_executor_.reset(new extensions::ScriptExecutor(guest_web_contents(),
499 &script_observers_));
500
501 notification_registrar_.Add(
502 this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
503 content::Source<WebContents>(guest_web_contents()));
504
505 notification_registrar_.Add(
506 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
507 content::Source<WebContents>(guest_web_contents()));
508
509 #if defined(OS_CHROMEOS)
510 chromeos::AccessibilityManager* accessibility_manager =
511 chromeos::AccessibilityManager::Get();
512 CHECK(accessibility_manager);
513 accessibility_subscription_ = accessibility_manager->RegisterCallback(
514 base::Bind(&WebViewGuest::OnAccessibilityStatusChanged,
515 base::Unretained(this)));
516 #endif
517
518 AttachWebViewHelpers(guest_web_contents());
519 }
520
466 bool WebViewGuest::IsDragAndDropEnabled() const { 521 bool WebViewGuest::IsDragAndDropEnabled() const {
467 return true; 522 return true;
468 } 523 }
469 524
470 void WebViewGuest::WillDestroy() { 525 void WebViewGuest::WillDestroy() {
471 if (!attached() && GetOpener()) 526 if (!attached() && GetOpener())
472 GetOpener()->pending_new_windows_.erase(this); 527 GetOpener()->pending_new_windows_.erase(this);
473 DestroyUnattachedWindows(); 528 DestroyUnattachedWindows();
474 } 529 }
475 530
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 const std::string& name) { 622 const std::string& name) {
568 if (!is_top_level) 623 if (!is_top_level)
569 return; 624 return;
570 625
571 if (name_ == name) 626 if (name_ == name)
572 return; 627 return;
573 628
574 ReportFrameNameChange(name); 629 ReportFrameNameChange(name);
575 } 630 }
576 631
577 WebViewGuest* WebViewGuest::CreateNewGuestWindow( 632 WebViewGuest* WebViewGuest::CreateNewGuestWebViewWindow(
578 const content::OpenURLParams& params) { 633 const content::OpenURLParams& params) {
579 GuestViewManager* guest_manager = 634 GuestViewManager* guest_manager =
580 GuestViewManager::FromBrowserContext(browser_context()); 635 GuestViewManager::FromBrowserContext(browser_context());
581 // Allocate a new instance ID for the new guest.
582 int instance_id = guest_manager->GetNextInstanceID();
583
584 // Set the attach params to use the same partition as the opener. 636 // Set the attach params to use the same partition as the opener.
585 // We pull the partition information from the site's URL, which is of the 637 // We pull the partition information from the site's URL, which is of the
586 // form guest://site/{persist}?{partition_name}. 638 // form guest://site/{persist}?{partition_name}.
587 const GURL& site_url = guest_web_contents()->GetSiteInstance()->GetSiteURL(); 639 const GURL& site_url = guest_web_contents()->GetSiteInstance()->GetSiteURL();
588 scoped_ptr<base::DictionaryValue> create_params(extra_params()->DeepCopy());
589 const std::string storage_partition_id = 640 const std::string storage_partition_id =
590 GetStoragePartitionIdFromSiteURL(site_url); 641 GetStoragePartitionIdFromSiteURL(site_url);
591 create_params->SetString(webview::kStoragePartitionId, storage_partition_id); 642 base::DictionaryValue create_params;
643 create_params.SetString(webview::kStoragePartitionId, storage_partition_id);
592 644
593 WebContents* new_guest_web_contents = 645 WebContents* new_guest_web_contents =
594 guest_manager->CreateGuest(guest_web_contents()->GetSiteInstance(), 646 guest_manager->CreateGuest(
595 instance_id, 647 WebViewGuest::Type,
596 create_params.Pass()); 648 embedder_extension_id(),
649 embedder_web_contents()->GetRenderProcessHost(),
650 create_params);
597 WebViewGuest* new_guest = 651 WebViewGuest* new_guest =
598 WebViewGuest::FromWebContents(new_guest_web_contents); 652 WebViewGuest::FromWebContents(new_guest_web_contents);
599 new_guest->SetOpener(this); 653 new_guest->SetOpener(this);
600 654
601 // Take ownership of |new_guest|. 655 // Take ownership of |new_guest|.
602 pending_new_windows_.insert( 656 pending_new_windows_.insert(
603 std::make_pair(new_guest, NewWindowInfo(params.url, std::string()))); 657 std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
604 658
605 // Request permission to show the new window. 659 // Request permission to show the new window.
606 RequestNewWindowPermission(params.disposition, gfx::Rect(), 660 RequestNewWindowPermission(params.disposition, gfx::Rect(),
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 WebContents* web_contents) { 1170 WebContents* web_contents) {
1117 content::BrowserThread::PostTask( 1171 content::BrowserThread::PostTask(
1118 content::BrowserThread::IO, FROM_HERE, 1172 content::BrowserThread::IO, FROM_HERE,
1119 base::Bind( 1173 base::Bind(
1120 &ExtensionRendererState::RemoveWebView, 1174 &ExtensionRendererState::RemoveWebView,
1121 base::Unretained(ExtensionRendererState::GetInstance()), 1175 base::Unretained(ExtensionRendererState::GetInstance()),
1122 web_contents->GetRenderProcessHost()->GetID(), 1176 web_contents->GetRenderProcessHost()->GetID(),
1123 web_contents->GetRoutingID())); 1177 web_contents->GetRoutingID()));
1124 } 1178 }
1125 1179
1180 content::WebContents* WebViewGuest::CreateNewGuestWindow(
1181 content::WebContents::CreateParams* create_params) {
1182 GuestViewManager* guest_manager =
1183 GuestViewManager::FromBrowserContext(browser_context());
1184 return guest_manager->CreateGuestWithWebContentsParams(
1185 WebViewGuest::Type,
1186 embedder_extension_id(),
1187 embedder_web_contents()->GetRenderProcessHost(),
1188 create_params);
1189 }
1190
1126 void WebViewGuest::SizeChanged(const gfx::Size& old_size, 1191 void WebViewGuest::SizeChanged(const gfx::Size& old_size,
1127 const gfx::Size& new_size) { 1192 const gfx::Size& new_size) {
1128 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); 1193 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
1129 args->SetInteger(webview::kOldHeight, old_size.height()); 1194 args->SetInteger(webview::kOldHeight, old_size.height());
1130 args->SetInteger(webview::kOldWidth, old_size.width()); 1195 args->SetInteger(webview::kOldWidth, old_size.width());
1131 args->SetInteger(webview::kNewHeight, new_size.height()); 1196 args->SetInteger(webview::kNewHeight, new_size.height());
1132 args->SetInteger(webview::kNewWidth, new_size.width()); 1197 args->SetInteger(webview::kNewWidth, new_size.width());
1133 DispatchEvent( 1198 DispatchEvent(
1134 new GuestViewBase::Event(webview::kEventSizeChanged, args.Pass())); 1199 new GuestViewBase::Event(webview::kEventSizeChanged, args.Pass()));
1135 } 1200 }
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1461 NewWindowInfo new_window_info(params.url, old_target_url.name); 1526 NewWindowInfo new_window_info(params.url, old_target_url.name);
1462 it->second = new_window_info; 1527 it->second = new_window_info;
1463 return NULL; 1528 return NULL;
1464 } 1529 }
1465 if (params.disposition == CURRENT_TAB) { 1530 if (params.disposition == CURRENT_TAB) {
1466 // This can happen for cross-site redirects. 1531 // This can happen for cross-site redirects.
1467 LoadURLWithParams(params.url, params.referrer, params.transition, source); 1532 LoadURLWithParams(params.url, params.referrer, params.transition, source);
1468 return source; 1533 return source;
1469 } 1534 }
1470 1535
1471 return CreateNewGuestWindow(params)->guest_web_contents(); 1536 return CreateNewGuestWebViewWindow(params)->guest_web_contents();
1472 } 1537 }
1473 1538
1474 void WebViewGuest::WebContentsCreated(WebContents* source_contents, 1539 void WebViewGuest::WebContentsCreated(WebContents* source_contents,
1475 int opener_render_frame_id, 1540 int opener_render_frame_id,
1476 const base::string16& frame_name, 1541 const base::string16& frame_name,
1477 const GURL& target_url, 1542 const GURL& target_url,
1478 content::WebContents* new_contents) { 1543 content::WebContents* new_contents) {
1479 WebViewGuest* guest = WebViewGuest::FromWebContents(new_contents); 1544 WebViewGuest* guest = WebViewGuest::FromWebContents(new_contents);
1480 CHECK(guest); 1545 CHECK(guest);
1481 guest->SetOpener(this); 1546 guest->SetOpener(this);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1576 bool allow, 1641 bool allow,
1577 const std::string& user_input) { 1642 const std::string& user_input) {
1578 WebViewGuest* guest = 1643 WebViewGuest* guest =
1579 WebViewGuest::From(embedder_render_process_id(), new_window_instance_id); 1644 WebViewGuest::From(embedder_render_process_id(), new_window_instance_id);
1580 if (!guest) 1645 if (!guest)
1581 return; 1646 return;
1582 1647
1583 if (!allow) 1648 if (!allow)
1584 guest->Destroy(); 1649 guest->Destroy();
1585 } 1650 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698