OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/renderer/render_view_impl.h" | 5 #include "content/renderer/render_view_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 #include "content/renderer/media/media_stream_impl.h" | 81 #include "content/renderer/media/media_stream_impl.h" |
82 #include "content/renderer/media/render_audiosourceprovider.h" | 82 #include "content/renderer/media/render_audiosourceprovider.h" |
83 #include "content/renderer/media/render_media_log.h" | 83 #include "content/renderer/media/render_media_log.h" |
84 #include "content/renderer/media/renderer_gpu_video_decoder_factories.h" | 84 #include "content/renderer/media/renderer_gpu_video_decoder_factories.h" |
85 #include "content/renderer/media/rtc_peer_connection_handler.h" | 85 #include "content/renderer/media/rtc_peer_connection_handler.h" |
86 #include "content/renderer/mhtml_generator.h" | 86 #include "content/renderer/mhtml_generator.h" |
87 #include "content/renderer/notification_provider.h" | 87 #include "content/renderer/notification_provider.h" |
88 #include "content/renderer/plugin_channel_host.h" | 88 #include "content/renderer/plugin_channel_host.h" |
89 #include "content/renderer/render_process.h" | 89 #include "content/renderer/render_process.h" |
90 #include "content/renderer/render_thread_impl.h" | 90 #include "content/renderer/render_thread_impl.h" |
| 91 #include "content/renderer/render_view_impl_params.h" |
91 #include "content/renderer/render_view_mouse_lock_dispatcher.h" | 92 #include "content/renderer/render_view_mouse_lock_dispatcher.h" |
92 #include "content/renderer/render_widget_fullscreen_pepper.h" | 93 #include "content/renderer/render_widget_fullscreen_pepper.h" |
93 #include "content/renderer/renderer_accessibility.h" | 94 #include "content/renderer/renderer_accessibility.h" |
94 #include "content/renderer/renderer_accessibility_complete.h" | 95 #include "content/renderer/renderer_accessibility_complete.h" |
95 #include "content/renderer/renderer_accessibility_focus_only.h" | 96 #include "content/renderer/renderer_accessibility_focus_only.h" |
96 #include "content/renderer/renderer_webapplicationcachehost_impl.h" | 97 #include "content/renderer/renderer_webapplicationcachehost_impl.h" |
97 #include "content/renderer/renderer_webcolorchooser_impl.h" | 98 #include "content/renderer/renderer_webcolorchooser_impl.h" |
98 #include "content/renderer/speech_recognition_dispatcher.h" | 99 #include "content/renderer/speech_recognition_dispatcher.h" |
99 #include "content/renderer/text_input_client_observer.h" | 100 #include "content/renderer/text_input_client_observer.h" |
100 #include "content/renderer/v8_value_converter_impl.h" | 101 #include "content/renderer/v8_value_converter_impl.h" |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 static const float kScalingIncrement = 0.1f; | 353 static const float kScalingIncrement = 0.1f; |
353 | 354 |
354 static const float kScalingIncrementForGesture = 0.01f; | 355 static const float kScalingIncrementForGesture = 0.01f; |
355 | 356 |
356 #if defined(OS_ANDROID) | 357 #if defined(OS_ANDROID) |
357 // Delay between tapping in content and launching the associated android intent. | 358 // Delay between tapping in content and launching the associated android intent. |
358 // Used to allow users see what has been recognized as content. | 359 // Used to allow users see what has been recognized as content. |
359 static const size_t kContentIntentDelayMilliseconds = 700; | 360 static const size_t kContentIntentDelayMilliseconds = 700; |
360 #endif | 361 #endif |
361 | 362 |
| 363 static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) = |
| 364 NULL; |
| 365 |
362 static RenderViewImpl* FromRoutingID(int32 routing_id) { | 366 static RenderViewImpl* FromRoutingID(int32 routing_id) { |
363 return static_cast<RenderViewImpl*>( | 367 return static_cast<RenderViewImpl*>( |
364 ChildThread::current()->ResolveRoute(routing_id)); | 368 ChildThread::current()->ResolveRoute(routing_id)); |
365 } | 369 } |
366 | 370 |
367 static WebKit::WebFrame* FindFrameByID(WebKit::WebFrame* root, int frame_id) { | 371 static WebKit::WebFrame* FindFrameByID(WebKit::WebFrame* root, int frame_id) { |
368 for (WebFrame* frame = root; frame; frame = frame->traverseNext(false)) { | 372 for (WebFrame* frame = root; frame; frame = frame->traverseNext(false)) { |
369 if (frame->identifier() == frame_id) | 373 if (frame->identifier() == frame_id) |
370 return frame; | 374 return frame; |
371 } | 375 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 return -1; | 533 return -1; |
530 | 534 |
531 if (item.httpBody().isNull()) | 535 if (item.httpBody().isNull()) |
532 return -1; | 536 return -1; |
533 | 537 |
534 return item.httpBody().identifier(); | 538 return item.httpBody().identifier(); |
535 } | 539 } |
536 | 540 |
537 } // namespace | 541 } // namespace |
538 | 542 |
539 RenderViewImpl::RenderViewImpl( | 543 RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) |
540 int32 opener_id, | 544 : RenderWidget(WebKit::WebPopupTypeNone, |
541 const RendererPreferences& renderer_prefs, | 545 params->screen_info, |
542 const WebPreferences& webkit_prefs, | 546 params->swapped_out), |
543 SharedRenderViewCounter* counter, | 547 webkit_preferences_(params->webkit_prefs), |
544 int32 routing_id, | |
545 int32 surface_id, | |
546 int64 session_storage_namespace_id, | |
547 const string16& frame_name, | |
548 bool is_renderer_created, | |
549 bool swapped_out, | |
550 int32 next_page_id, | |
551 const WebKit::WebScreenInfo& screen_info, | |
552 AccessibilityMode accessibility_mode) | |
553 : RenderWidget(WebKit::WebPopupTypeNone, screen_info, swapped_out), | |
554 webkit_preferences_(webkit_prefs), | |
555 send_content_state_immediately_(false), | 548 send_content_state_immediately_(false), |
556 enabled_bindings_(0), | 549 enabled_bindings_(0), |
557 send_preferred_size_changes_(false), | 550 send_preferred_size_changes_(false), |
558 is_loading_(false), | 551 is_loading_(false), |
559 navigation_gesture_(NavigationGestureUnknown), | 552 navigation_gesture_(NavigationGestureUnknown), |
560 opened_by_user_gesture_(true), | 553 opened_by_user_gesture_(true), |
561 opener_suppressed_(false), | 554 opener_suppressed_(false), |
562 page_id_(-1), | 555 page_id_(-1), |
563 last_page_id_sent_to_browser_(-1), | 556 last_page_id_sent_to_browser_(-1), |
564 next_page_id_(next_page_id), | 557 next_page_id_(params->next_page_id), |
565 history_list_offset_(-1), | 558 history_list_offset_(-1), |
566 history_list_length_(0), | 559 history_list_length_(0), |
567 target_url_status_(TARGET_NONE), | 560 target_url_status_(TARGET_NONE), |
568 selection_text_offset_(0), | 561 selection_text_offset_(0), |
569 cached_is_main_frame_pinned_to_left_(false), | 562 cached_is_main_frame_pinned_to_left_(false), |
570 cached_is_main_frame_pinned_to_right_(false), | 563 cached_is_main_frame_pinned_to_right_(false), |
571 cached_has_main_frame_horizontal_scrollbar_(false), | 564 cached_has_main_frame_horizontal_scrollbar_(false), |
572 cached_has_main_frame_vertical_scrollbar_(false), | 565 cached_has_main_frame_vertical_scrollbar_(false), |
573 ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)), | 566 ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)), |
574 geolocation_dispatcher_(NULL), | 567 geolocation_dispatcher_(NULL), |
575 input_tag_speech_dispatcher_(NULL), | 568 input_tag_speech_dispatcher_(NULL), |
576 speech_recognition_dispatcher_(NULL), | 569 speech_recognition_dispatcher_(NULL), |
577 device_orientation_dispatcher_(NULL), | 570 device_orientation_dispatcher_(NULL), |
578 media_stream_dispatcher_(NULL), | 571 media_stream_dispatcher_(NULL), |
579 media_stream_impl_(NULL), | 572 media_stream_impl_(NULL), |
580 devtools_agent_(NULL), | 573 devtools_agent_(NULL), |
581 accessibility_mode_(AccessibilityModeOff), | 574 accessibility_mode_(AccessibilityModeOff), |
582 renderer_accessibility_(NULL), | 575 renderer_accessibility_(NULL), |
583 java_bridge_dispatcher_(NULL), | 576 java_bridge_dispatcher_(NULL), |
584 mouse_lock_dispatcher_(NULL), | 577 mouse_lock_dispatcher_(NULL), |
585 #if defined(OS_ANDROID) | 578 #if defined(OS_ANDROID) |
586 body_background_color_(SK_ColorWHITE), | 579 body_background_color_(SK_ColorWHITE), |
587 update_frame_info_scheduled_(false), | 580 update_frame_info_scheduled_(false), |
588 expected_content_intent_id_(0), | 581 expected_content_intent_id_(0), |
589 media_player_proxy_(NULL), | 582 media_player_proxy_(NULL), |
590 synchronous_find_active_match_ordinal_(-1), | 583 synchronous_find_active_match_ordinal_(-1), |
591 ALLOW_THIS_IN_INITIALIZER_LIST( | 584 ALLOW_THIS_IN_INITIALIZER_LIST( |
592 load_progress_tracker_(new LoadProgressTracker(this))), | 585 load_progress_tracker_(new LoadProgressTracker(this))), |
593 #endif | 586 #endif |
594 session_storage_namespace_id_(session_storage_namespace_id), | 587 session_storage_namespace_id_(params->session_storage_namespace_id), |
595 handling_select_range_(false), | 588 handling_select_range_(false), |
596 #if defined(OS_WIN) | 589 #if defined(OS_WIN) |
597 focused_plugin_id_(-1), | 590 focused_plugin_id_(-1), |
598 #endif | 591 #endif |
599 updating_frame_tree_(false), | 592 updating_frame_tree_(false), |
600 pending_frame_tree_update_(false), | 593 pending_frame_tree_update_(false), |
601 target_process_id_(0), | 594 target_process_id_(0), |
602 target_routing_id_(0), | 595 target_routing_id_(0), |
603 ALLOW_THIS_IN_INITIALIZER_LIST(pepper_delegate_(this)) { | 596 ALLOW_THIS_IN_INITIALIZER_LIST(pepper_delegate_(this)) { |
604 set_throttle_input_events(renderer_prefs.throttle_input_events); | 597 set_throttle_input_events(params->renderer_prefs.throttle_input_events); |
605 routing_id_ = routing_id; | 598 routing_id_ = params->routing_id; |
606 surface_id_ = surface_id; | 599 surface_id_ = params->surface_id; |
607 if (opener_id != MSG_ROUTING_NONE && is_renderer_created) | 600 if (params->opener_id != MSG_ROUTING_NONE && params->is_renderer_created) |
608 opener_id_ = opener_id; | 601 opener_id_ = params->opener_id; |
609 | 602 |
610 // Ensure we start with a valid next_page_id_ from the browser. | 603 // Ensure we start with a valid next_page_id_ from the browser. |
611 DCHECK_GE(next_page_id_, 0); | 604 DCHECK_GE(next_page_id_, 0); |
612 | 605 |
613 #if defined(ENABLE_NOTIFICATIONS) | 606 #if defined(ENABLE_NOTIFICATIONS) |
614 notification_provider_ = new NotificationProvider(this); | 607 notification_provider_ = new NotificationProvider(this); |
615 #else | 608 #else |
616 notification_provider_ = NULL; | 609 notification_provider_ = NULL; |
617 #endif | 610 #endif |
618 | 611 |
(...skipping 12 matching lines...) Expand all Loading... |
631 ? command_line.GetSwitchValueASCII(switches::kNetworkCountryIso) | 624 ? command_line.GetSwitchValueASCII(switches::kNetworkCountryIso) |
632 : device_info->GetNetworkCountryIso(); | 625 : device_info->GetNetworkCountryIso(); |
633 content_detectors_.push_back(linked_ptr<ContentDetector>( | 626 content_detectors_.push_back(linked_ptr<ContentDetector>( |
634 new AddressDetector())); | 627 new AddressDetector())); |
635 content_detectors_.push_back(linked_ptr<ContentDetector>( | 628 content_detectors_.push_back(linked_ptr<ContentDetector>( |
636 new PhoneNumberDetector(region_code))); | 629 new PhoneNumberDetector(region_code))); |
637 content_detectors_.push_back(linked_ptr<ContentDetector>( | 630 content_detectors_.push_back(linked_ptr<ContentDetector>( |
638 new EmailDetector())); | 631 new EmailDetector())); |
639 #endif | 632 #endif |
640 | 633 |
641 if (counter) { | 634 if (params->counter) { |
642 shared_popup_counter_ = counter; | 635 shared_popup_counter_ = params->counter; |
643 // Only count this if it isn't swapped out upon creation. | 636 // Only count this if it isn't swapped out upon creation. |
644 if (!swapped_out) | 637 if (!params->swapped_out) |
645 shared_popup_counter_->data++; | 638 shared_popup_counter_->data++; |
646 decrement_shared_popup_at_destruction_ = true; | 639 decrement_shared_popup_at_destruction_ = true; |
647 } else { | 640 } else { |
648 shared_popup_counter_ = new SharedRenderViewCounter(0); | 641 shared_popup_counter_ = new SharedRenderViewCounter(0); |
649 decrement_shared_popup_at_destruction_ = false; | 642 decrement_shared_popup_at_destruction_ = false; |
650 } | 643 } |
651 | 644 |
652 RenderThread::Get()->AddRoute(routing_id_, this); | 645 RenderThread::Get()->AddRoute(routing_id_, this); |
653 // Take a reference on behalf of the RenderThread. This will be balanced | 646 // Take a reference on behalf of the RenderThread. This will be balanced |
654 // when we receive ViewMsg_ClosePage. | 647 // when we receive ViewMsg_ClosePage. |
655 AddRef(); | 648 AddRef(); |
656 | 649 |
657 // If this is a popup, we must wait for the CreatingNew_ACK message before | 650 // If this is a popup, we must wait for the CreatingNew_ACK message before |
658 // completing initialization. Otherwise, we can finish it now. | 651 // completing initialization. Otherwise, we can finish it now. |
659 if (opener_id_ == MSG_ROUTING_NONE) { | 652 if (opener_id_ == MSG_ROUTING_NONE) { |
660 did_show_ = true; | 653 did_show_ = true; |
661 CompleteInit(); | 654 CompleteInit(); |
662 } | 655 } |
663 | 656 |
664 g_view_map.Get().insert(std::make_pair(webview(), this)); | 657 g_view_map.Get().insert(std::make_pair(webview(), this)); |
665 webview()->setDeviceScaleFactor(device_scale_factor_); | 658 webview()->setDeviceScaleFactor(device_scale_factor_); |
666 webkit_preferences_.Apply(webview()); | 659 webkit_preferences_.Apply(webview()); |
667 webview()->initializeMainFrame(this); | 660 webview()->initializeMainFrame(this); |
668 if (!frame_name.empty()) | 661 if (!params->frame_name.empty()) |
669 webview()->mainFrame()->setName(frame_name); | 662 webview()->mainFrame()->setName(params->frame_name); |
670 webview()->settings()->setMinimumTimerInterval( | 663 webview()->settings()->setMinimumTimerInterval( |
671 is_hidden() ? webkit_glue::kBackgroundTabTimerInterval : | 664 is_hidden() ? webkit_glue::kBackgroundTabTimerInterval : |
672 webkit_glue::kForegroundTabTimerInterval); | 665 webkit_glue::kForegroundTabTimerInterval); |
673 | 666 |
674 OnSetRendererPrefs(renderer_prefs); | 667 OnSetRendererPrefs(params->renderer_prefs); |
675 | 668 |
676 #if defined(ENABLE_WEBRTC) | 669 #if defined(ENABLE_WEBRTC) |
677 if (!media_stream_dispatcher_) | 670 if (!media_stream_dispatcher_) |
678 media_stream_dispatcher_ = new MediaStreamDispatcher(this); | 671 media_stream_dispatcher_ = new MediaStreamDispatcher(this); |
679 #endif | 672 #endif |
680 | 673 |
681 new MHTMLGenerator(this); | 674 new MHTMLGenerator(this); |
682 #if defined(OS_MACOSX) | 675 #if defined(OS_MACOSX) |
683 new TextInputClientObserver(this); | 676 new TextInputClientObserver(this); |
684 #endif // defined(OS_MACOSX) | 677 #endif // defined(OS_MACOSX) |
685 | 678 |
686 #if defined(OS_ANDROID) | 679 #if defined(OS_ANDROID) |
687 media_player_manager_.reset( | 680 media_player_manager_.reset( |
688 new webkit_media::WebMediaPlayerManagerAndroid()); | 681 new webkit_media::WebMediaPlayerManagerAndroid()); |
689 #endif | 682 #endif |
690 | 683 |
691 // The next group of objects all implement RenderViewObserver, so are deleted | 684 // The next group of objects all implement RenderViewObserver, so are deleted |
692 // along with the RenderView automatically. | 685 // along with the RenderView automatically. |
693 devtools_agent_ = new DevToolsAgent(this); | 686 devtools_agent_ = new DevToolsAgent(this); |
694 mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this); | 687 mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this); |
695 intents_host_ = new WebIntentsHost(this); | 688 intents_host_ = new WebIntentsHost(this); |
696 | 689 |
697 // Create renderer_accessibility_ if needed. | 690 // Create renderer_accessibility_ if needed. |
698 OnSetAccessibilityMode(accessibility_mode); | 691 OnSetAccessibilityMode(params->accessibility_mode); |
699 | 692 |
700 new IdleUserDetector(this); | 693 new IdleUserDetector(this); |
701 | 694 |
702 if (command_line.HasSwitch(switches::kDomAutomationController)) | 695 if (command_line.HasSwitch(switches::kDomAutomationController)) |
703 enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION; | 696 enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION; |
704 | 697 |
705 ProcessViewLayoutFlags(command_line); | 698 ProcessViewLayoutFlags(command_line); |
706 | 699 |
707 GetContentClient()->renderer()->RenderViewCreated(this); | 700 GetContentClient()->renderer()->RenderViewCreated(this); |
708 | 701 |
709 // If we have an opener_id but we weren't created by a renderer, then | 702 // If we have an opener_id but we weren't created by a renderer, then |
710 // it's the browser asking us to set our opener to another RenderView. | 703 // it's the browser asking us to set our opener to another RenderView. |
711 if (opener_id != MSG_ROUTING_NONE && !is_renderer_created) { | 704 if (params->opener_id != MSG_ROUTING_NONE && !params->is_renderer_created) { |
712 RenderViewImpl* opener_view = FromRoutingID(opener_id); | 705 RenderViewImpl* opener_view = FromRoutingID(params->opener_id); |
713 if (opener_view) | 706 if (opener_view) |
714 webview()->mainFrame()->setOpener(opener_view->webview()->mainFrame()); | 707 webview()->mainFrame()->setOpener(opener_view->webview()->mainFrame()); |
715 } | 708 } |
716 | 709 |
717 // If we are initially swapped out, navigate to kSwappedOutURL. | 710 // If we are initially swapped out, navigate to kSwappedOutURL. |
718 // This ensures we are in a unique origin that others cannot script. | 711 // This ensures we are in a unique origin that others cannot script. |
719 if (is_swapped_out_) | 712 if (is_swapped_out_) |
720 NavigateToSwappedOutURL(webview()->mainFrame()); | 713 NavigateToSwappedOutURL(webview()->mainFrame()); |
721 } | 714 } |
722 | 715 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 int32 routing_id, | 779 int32 routing_id, |
787 int32 surface_id, | 780 int32 surface_id, |
788 int64 session_storage_namespace_id, | 781 int64 session_storage_namespace_id, |
789 const string16& frame_name, | 782 const string16& frame_name, |
790 bool is_renderer_created, | 783 bool is_renderer_created, |
791 bool swapped_out, | 784 bool swapped_out, |
792 int32 next_page_id, | 785 int32 next_page_id, |
793 const WebKit::WebScreenInfo& screen_info, | 786 const WebKit::WebScreenInfo& screen_info, |
794 AccessibilityMode accessibility_mode) { | 787 AccessibilityMode accessibility_mode) { |
795 DCHECK(routing_id != MSG_ROUTING_NONE); | 788 DCHECK(routing_id != MSG_ROUTING_NONE); |
796 return new RenderViewImpl( | 789 RenderViewImplParams params( |
797 opener_id, | 790 opener_id, |
798 renderer_prefs, | 791 renderer_prefs, |
799 webkit_prefs, | 792 webkit_prefs, |
800 counter, | 793 counter, |
801 routing_id, | 794 routing_id, |
802 surface_id, | 795 surface_id, |
803 session_storage_namespace_id, | 796 session_storage_namespace_id, |
804 frame_name, | 797 frame_name, |
805 is_renderer_created, | 798 is_renderer_created, |
806 swapped_out, | 799 swapped_out, |
807 next_page_id, | 800 next_page_id, |
808 screen_info, | 801 screen_info, |
809 accessibility_mode); | 802 accessibility_mode); |
| 803 if (g_create_render_view_impl) |
| 804 return g_create_render_view_impl(¶ms); |
| 805 return new RenderViewImpl(¶ms); |
| 806 } |
| 807 |
| 808 // static |
| 809 void RenderViewImpl::InstallCreateHook( |
| 810 RenderViewImpl* (*create_render_view_impl)(RenderViewImplParams*)) { |
| 811 CHECK(!g_create_render_view_impl); |
| 812 g_create_render_view_impl = create_render_view_impl; |
810 } | 813 } |
811 | 814 |
812 void RenderViewImpl::AddObserver(RenderViewObserver* observer) { | 815 void RenderViewImpl::AddObserver(RenderViewObserver* observer) { |
813 observers_.AddObserver(observer); | 816 observers_.AddObserver(observer); |
814 } | 817 } |
815 | 818 |
816 void RenderViewImpl::RemoveObserver(RenderViewObserver* observer) { | 819 void RenderViewImpl::RemoveObserver(RenderViewObserver* observer) { |
817 observer->RenderViewGone(); | 820 observer->RenderViewGone(); |
818 observers_.RemoveObserver(observer); | 821 observers_.RemoveObserver(observer); |
819 } | 822 } |
(...skipping 5541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6361 } | 6364 } |
6362 #endif | 6365 #endif |
6363 | 6366 |
6364 void RenderViewImpl::OnReleaseDisambiguationPopupDIB( | 6367 void RenderViewImpl::OnReleaseDisambiguationPopupDIB( |
6365 TransportDIB::Handle dib_handle) { | 6368 TransportDIB::Handle dib_handle) { |
6366 TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle); | 6369 TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle); |
6367 RenderProcess::current()->ReleaseTransportDIB(dib); | 6370 RenderProcess::current()->ReleaseTransportDIB(dib); |
6368 } | 6371 } |
6369 | 6372 |
6370 } // namespace content | 6373 } // namespace content |
OLD | NEW |