OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_frame_impl.h" | 5 #include "content/renderer/render_frame_impl.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
971 blink::WebFrame* previous_sibling_web_frame = nullptr; | 971 blink::WebFrame* previous_sibling_web_frame = nullptr; |
972 RenderFrameProxy* previous_sibling_proxy = | 972 RenderFrameProxy* previous_sibling_proxy = |
973 RenderFrameProxy::FromRoutingID(previous_sibling_routing_id); | 973 RenderFrameProxy::FromRoutingID(previous_sibling_routing_id); |
974 if (previous_sibling_proxy) | 974 if (previous_sibling_proxy) |
975 previous_sibling_web_frame = previous_sibling_proxy->web_frame(); | 975 previous_sibling_web_frame = previous_sibling_proxy->web_frame(); |
976 | 976 |
977 // Create the RenderFrame and WebLocalFrame, linking the two. | 977 // Create the RenderFrame and WebLocalFrame, linking the two. |
978 render_frame = | 978 render_frame = |
979 RenderFrameImpl::Create(parent_proxy->render_view(), routing_id); | 979 RenderFrameImpl::Create(parent_proxy->render_view(), routing_id); |
980 render_frame->InitializeBlameContext(FromRoutingID(parent_routing_id)); | 980 render_frame->InitializeBlameContext(FromRoutingID(parent_routing_id)); |
981 render_frame->unique_name_helper_.set_propagated_name( | |
982 replicated_state.unique_name); | |
981 web_frame = parent_web_frame->createLocalChild( | 983 web_frame = parent_web_frame->createLocalChild( |
982 replicated_state.scope, WebString::fromUTF8(replicated_state.name), | 984 replicated_state.scope, WebString::fromUTF8(replicated_state.name), |
983 WebString::fromUTF8(replicated_state.unique_name), | |
984 replicated_state.sandbox_flags, render_frame, | 985 replicated_state.sandbox_flags, render_frame, |
985 render_frame->blink_interface_provider_.get(), | 986 render_frame->blink_interface_provider_.get(), |
986 render_frame->blink_interface_registry_.get(), | 987 render_frame->blink_interface_registry_.get(), |
987 previous_sibling_web_frame, | 988 previous_sibling_web_frame, |
988 ConvertFrameOwnerPropertiesToWebFrameOwnerProperties( | 989 ConvertFrameOwnerPropertiesToWebFrameOwnerProperties( |
989 frame_owner_properties), | 990 frame_owner_properties), |
990 ResolveOpener(opener_routing_id)); | 991 ResolveOpener(opener_routing_id)); |
991 | 992 |
992 // The RenderFrame is created and inserted into the frame tree in the above | 993 // The RenderFrame is created and inserted into the frame tree in the above |
993 // call to createLocalChild. | 994 // call to createLocalChild. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1072 | 1073 |
1073 blink::WebURL RenderFrameImpl::overrideFlashEmbedWithHTML( | 1074 blink::WebURL RenderFrameImpl::overrideFlashEmbedWithHTML( |
1074 const blink::WebURL& url) { | 1075 const blink::WebURL& url) { |
1075 return GetContentClient()->renderer()->OverrideFlashEmbedWithHTML(url); | 1076 return GetContentClient()->renderer()->OverrideFlashEmbedWithHTML(url); |
1076 } | 1077 } |
1077 | 1078 |
1078 // RenderFrameImpl ---------------------------------------------------------- | 1079 // RenderFrameImpl ---------------------------------------------------------- |
1079 RenderFrameImpl::RenderFrameImpl(const CreateParams& params) | 1080 RenderFrameImpl::RenderFrameImpl(const CreateParams& params) |
1080 : frame_(NULL), | 1081 : frame_(NULL), |
1081 is_main_frame_(true), | 1082 is_main_frame_(true), |
1083 unique_name_helper_(this), | |
1082 in_browser_initiated_detach_(false), | 1084 in_browser_initiated_detach_(false), |
1083 in_frame_tree_(false), | 1085 in_frame_tree_(false), |
1084 render_view_(params.render_view), | 1086 render_view_(params.render_view), |
1085 routing_id_(params.routing_id), | 1087 routing_id_(params.routing_id), |
1086 proxy_routing_id_(MSG_ROUTING_NONE), | 1088 proxy_routing_id_(MSG_ROUTING_NONE), |
1087 #if BUILDFLAG(ENABLE_PLUGINS) | 1089 #if BUILDFLAG(ENABLE_PLUGINS) |
1088 plugin_power_saver_helper_(nullptr), | 1090 plugin_power_saver_helper_(nullptr), |
1089 plugin_find_handler_(nullptr), | 1091 plugin_find_handler_(nullptr), |
1090 #endif | 1092 #endif |
1091 cookie_jar_(this), | 1093 cookie_jar_(this), |
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3012 } | 3014 } |
3013 } | 3015 } |
3014 | 3016 |
3015 has_accessed_initial_document_ = true; | 3017 has_accessed_initial_document_ = true; |
3016 } | 3018 } |
3017 | 3019 |
3018 blink::WebLocalFrame* RenderFrameImpl::createChildFrame( | 3020 blink::WebLocalFrame* RenderFrameImpl::createChildFrame( |
3019 blink::WebLocalFrame* parent, | 3021 blink::WebLocalFrame* parent, |
3020 blink::WebTreeScopeType scope, | 3022 blink::WebTreeScopeType scope, |
3021 const blink::WebString& name, | 3023 const blink::WebString& name, |
3022 const blink::WebString& unique_name, | 3024 const blink::WebString& fallback_name, |
3023 blink::WebSandboxFlags sandbox_flags, | 3025 blink::WebSandboxFlags sandbox_flags, |
3024 const blink::WebFrameOwnerProperties& frame_owner_properties) { | 3026 const blink::WebFrameOwnerProperties& frame_owner_properties) { |
3025 // Synchronously notify the browser of a child frame creation to get the | 3027 // Synchronously notify the browser of a child frame creation to get the |
3026 // routing_id for the RenderFrame. | 3028 // routing_id for the RenderFrame. |
3027 int child_routing_id = MSG_ROUTING_NONE; | 3029 int child_routing_id = MSG_ROUTING_NONE; |
3028 FrameHostMsg_CreateChildFrame_Params params; | 3030 FrameHostMsg_CreateChildFrame_Params params; |
3029 params.parent_routing_id = routing_id_; | 3031 params.parent_routing_id = routing_id_; |
3030 params.scope = scope; | 3032 params.scope = scope; |
3031 params.frame_name = name.utf8(); | 3033 params.frame_name = name.utf8(); |
3032 params.frame_unique_name = unique_name.utf8(); | 3034 params.frame_unique_name = UniqueNameHelper::GenerateNameForNewChildFrame( |
3035 parent, | |
3036 params.frame_name.empty() ? fallback_name.utf8() : params.frame_name); | |
3033 params.sandbox_flags = sandbox_flags; | 3037 params.sandbox_flags = sandbox_flags; |
3034 params.frame_owner_properties = | 3038 params.frame_owner_properties = |
3035 ConvertWebFrameOwnerPropertiesToFrameOwnerProperties( | 3039 ConvertWebFrameOwnerPropertiesToFrameOwnerProperties( |
3036 frame_owner_properties); | 3040 frame_owner_properties); |
3037 Send(new FrameHostMsg_CreateChildFrame(params, &child_routing_id)); | 3041 Send(new FrameHostMsg_CreateChildFrame(params, &child_routing_id)); |
3038 | 3042 |
3039 // Allocation of routing id failed, so we can't create a child frame. This can | 3043 // Allocation of routing id failed, so we can't create a child frame. This can |
3040 // happen if the synchronous IPC message above has failed. This can | 3044 // happen if the synchronous IPC message above has failed. This can |
3041 // legitimately happen when the browser process has already destroyed | 3045 // legitimately happen when the browser process has already destroyed |
3042 // RenderProcessHost, but the renderer process hasn't quit yet. | 3046 // RenderProcessHost, but the renderer process hasn't quit yet. |
3043 if (child_routing_id == MSG_ROUTING_NONE) | 3047 if (child_routing_id == MSG_ROUTING_NONE) |
3044 return nullptr; | 3048 return nullptr; |
3045 | 3049 |
3046 // This method is always called by local frames, never remote frames. | 3050 // This method is always called by local frames, never remote frames. |
3047 | 3051 |
3048 // Tracing analysis uses this to find main frames when this value is | 3052 // Tracing analysis uses this to find main frames when this value is |
3049 // MSG_ROUTING_NONE, and build the frame tree otherwise. | 3053 // MSG_ROUTING_NONE, and build the frame tree otherwise. |
3050 TRACE_EVENT2("navigation,rail", "RenderFrameImpl::createChildFrame", | 3054 TRACE_EVENT2("navigation,rail", "RenderFrameImpl::createChildFrame", |
3051 "id", routing_id_, | 3055 "id", routing_id_, |
3052 "child", child_routing_id); | 3056 "child", child_routing_id); |
3053 | 3057 |
3054 // Create the RenderFrame and WebLocalFrame, linking the two. | 3058 // Create the RenderFrame and WebLocalFrame, linking the two. |
3055 RenderFrameImpl* child_render_frame = | 3059 RenderFrameImpl* child_render_frame = |
3056 RenderFrameImpl::Create(render_view_, child_routing_id); | 3060 RenderFrameImpl::Create(render_view_, child_routing_id); |
3061 child_render_frame->unique_name_helper_.set_propagated_name( | |
3062 params.frame_unique_name); | |
3057 child_render_frame->InitializeBlameContext(this); | 3063 child_render_frame->InitializeBlameContext(this); |
3058 blink::WebLocalFrame* web_frame = WebLocalFrame::create( | 3064 blink::WebLocalFrame* web_frame = WebLocalFrame::create( |
3059 scope, child_render_frame, | 3065 scope, child_render_frame, |
3060 child_render_frame->blink_interface_provider_.get(), | 3066 child_render_frame->blink_interface_provider_.get(), |
3061 child_render_frame->blink_interface_registry_.get()); | 3067 child_render_frame->blink_interface_registry_.get()); |
3062 child_render_frame->BindToWebFrame(web_frame); | 3068 child_render_frame->BindToWebFrame(web_frame); |
3063 | 3069 |
3064 // Add the frame to the frame tree and initialize it. | 3070 // Add the frame to the frame tree and initialize it. |
3065 parent->appendChild(web_frame); | 3071 parent->appendChild(web_frame); |
3066 child_render_frame->in_frame_tree_ = true; | 3072 child_render_frame->in_frame_tree_ = true; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3157 Send(new FrameHostMsg_FrameFocused(routing_id_)); | 3163 Send(new FrameHostMsg_FrameFocused(routing_id_)); |
3158 } | 3164 } |
3159 | 3165 |
3160 void RenderFrameImpl::willCommitProvisionalLoad(blink::WebLocalFrame* frame) { | 3166 void RenderFrameImpl::willCommitProvisionalLoad(blink::WebLocalFrame* frame) { |
3161 DCHECK_EQ(frame_, frame); | 3167 DCHECK_EQ(frame_, frame); |
3162 | 3168 |
3163 for (auto& observer : observers_) | 3169 for (auto& observer : observers_) |
3164 observer.WillCommitProvisionalLoad(); | 3170 observer.WillCommitProvisionalLoad(); |
3165 } | 3171 } |
3166 | 3172 |
3167 void RenderFrameImpl::didChangeName(const blink::WebString& name, | 3173 void RenderFrameImpl::didChangeName(const blink::WebString& name) { |
3168 const blink::WebString& unique_name) { | 3174 if (current_history_item_.isNull()) |
3169 Send(new FrameHostMsg_DidChangeName( | 3175 unique_name_helper_.UpdateName(name.utf8()); |
3170 routing_id_, name.utf8(), unique_name.utf8())); | 3176 Send(new FrameHostMsg_DidChangeName(routing_id_, name.utf8(), |
3177 unique_name_helper_.value())); | |
3171 | 3178 |
3172 if (!committed_first_load_) | 3179 if (!committed_first_load_) |
3173 name_changed_before_first_commit_ = true; | 3180 name_changed_before_first_commit_ = true; |
3174 } | 3181 } |
3175 | 3182 |
3176 void RenderFrameImpl::didEnforceInsecureRequestPolicy( | 3183 void RenderFrameImpl::didEnforceInsecureRequestPolicy( |
3177 blink::WebInsecureRequestPolicy policy) { | 3184 blink::WebInsecureRequestPolicy policy) { |
3178 Send(new FrameHostMsg_EnforceInsecureRequestPolicy(routing_id_, policy)); | 3185 Send(new FrameHostMsg_EnforceInsecureRequestPolicy(routing_id_, policy)); |
3179 } | 3186 } |
3180 | 3187 |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3611 new ViewHostMsg_DidFirstPaintAfterLoad(render_view_->routing_id_), | 3618 new ViewHostMsg_DidFirstPaintAfterLoad(render_view_->routing_id_), |
3612 MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE); | 3619 MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE); |
3613 } | 3620 } |
3614 | 3621 |
3615 // When we perform a new navigation, we need to update the last committed | 3622 // When we perform a new navigation, we need to update the last committed |
3616 // session history entry with state for the page we are leaving. Do this | 3623 // session history entry with state for the page we are leaving. Do this |
3617 // before updating the current history item. | 3624 // before updating the current history item. |
3618 SendUpdateState(); | 3625 SendUpdateState(); |
3619 | 3626 |
3620 // Update the current history item for this frame (both in default Chrome and | 3627 // Update the current history item for this frame (both in default Chrome and |
3621 // subframe FrameNavigationEntry modes). | 3628 // subframe FrameNavigationEntry modes). |
Charlie Reis
2017/03/02 23:59:17
Oops-- while you're here, can you kill this parent
dcheng
2017/03/03 10:22:08
Done.
| |
3622 current_history_item_ = item; | 3629 current_history_item_ = item; |
3630 current_history_item_.setTarget( | |
3631 blink::WebString::fromUTF8(unique_name_helper_.value())); | |
3623 | 3632 |
3624 InternalDocumentStateData* internal_data = | 3633 InternalDocumentStateData* internal_data = |
3625 InternalDocumentStateData::FromDocumentState(document_state); | 3634 InternalDocumentStateData::FromDocumentState(document_state); |
3626 | 3635 |
3627 if (internal_data->must_reset_scroll_and_scale_state()) { | 3636 if (internal_data->must_reset_scroll_and_scale_state()) { |
3628 render_view_->webview()->resetScrollAndScaleState(); | 3637 render_view_->webview()->resetScrollAndScaleState(); |
3629 internal_data->set_must_reset_scroll_and_scale_state(false); | 3638 internal_data->set_must_reset_scroll_and_scale_state(false); |
3630 } | 3639 } |
3631 | 3640 |
3632 const RequestNavigationParams& request_params = | 3641 const RequestNavigationParams& request_params = |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3677 } | 3686 } |
3678 } | 3687 } |
3679 | 3688 |
3680 // Remember that we've already processed this request, so we don't update | 3689 // Remember that we've already processed this request, so we don't update |
3681 // the session history again. We do this regardless of whether this is | 3690 // the session history again. We do this regardless of whether this is |
3682 // a session history navigation, because if we attempted a session history | 3691 // a session history navigation, because if we attempted a session history |
3683 // navigation without valid HistoryItem state, WebCore will think it is a | 3692 // navigation without valid HistoryItem state, WebCore will think it is a |
3684 // new navigation. | 3693 // new navigation. |
3685 navigation_state->set_request_committed(true); | 3694 navigation_state->set_request_committed(true); |
3686 | 3695 |
3687 SendDidCommitProvisionalLoad(frame, commit_type, item); | 3696 SendDidCommitProvisionalLoad(frame, commit_type, current_history_item_); |
Charlie Reis
2017/03/02 23:59:17
I suppose this is ok. It's a bit risky if anyone
dcheng
2017/03/03 10:22:08
I considered removing it as a function param and j
Charlie Reis
2017/03/20 20:11:38
Yes, I definitely support that.
It's a bit orthog
dcheng
2017/03/21 22:03:41
Done.
| |
3688 | 3697 |
3689 // Check whether we have new encoding name. | 3698 // Check whether we have new encoding name. |
3690 UpdateEncoding(frame, frame->view()->pageEncoding().utf8()); | 3699 UpdateEncoding(frame, frame->view()->pageEncoding().utf8()); |
3691 } | 3700 } |
3692 | 3701 |
3693 void RenderFrameImpl::didCreateNewDocument(blink::WebLocalFrame* frame) { | 3702 void RenderFrameImpl::didCreateNewDocument(blink::WebLocalFrame* frame) { |
3694 DCHECK(!frame_ || frame_ == frame); | 3703 DCHECK(!frame_ || frame_ == frame); |
3695 | 3704 |
3696 for (auto& observer : observers_) | 3705 for (auto& observer : observers_) |
3697 observer.DidCreateNewDocument(); | 3706 observer.DidCreateNewDocument(); |
(...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5027 CHECK_NE(proxy_routing_id_, MSG_ROUTING_NONE); | 5036 CHECK_NE(proxy_routing_id_, MSG_ROUTING_NONE); |
5028 CHECK(!in_frame_tree_); | 5037 CHECK(!in_frame_tree_); |
5029 | 5038 |
5030 // The proxy should always exist. If it was detached while the provisional | 5039 // The proxy should always exist. If it was detached while the provisional |
5031 // LocalFrame was being navigated, the provisional frame would've been | 5040 // LocalFrame was being navigated, the provisional frame would've been |
5032 // cleaned up by RenderFrameProxy::frameDetached. See | 5041 // cleaned up by RenderFrameProxy::frameDetached. See |
5033 // https://crbug.com/526304 and https://crbug.com/568676 for context. | 5042 // https://crbug.com/526304 and https://crbug.com/568676 for context. |
5034 RenderFrameProxy* proxy = RenderFrameProxy::FromRoutingID(proxy_routing_id_); | 5043 RenderFrameProxy* proxy = RenderFrameProxy::FromRoutingID(proxy_routing_id_); |
5035 CHECK(proxy); | 5044 CHECK(proxy); |
5036 | 5045 |
5046 unique_name_helper_.set_propagated_name(proxy->unique_name()); | |
5047 | |
5048 // Note: Calling swap() will detach and delete |proxy|, so do not reference it | |
5049 // after this. | |
5037 int proxy_routing_id = proxy_routing_id_; | 5050 int proxy_routing_id = proxy_routing_id_; |
5038 if (!proxy->web_frame()->swap(frame_)) | 5051 if (!proxy->web_frame()->swap(frame_)) |
5039 return false; | 5052 return false; |
5040 | 5053 |
5041 proxy_routing_id_ = MSG_ROUTING_NONE; | 5054 proxy_routing_id_ = MSG_ROUTING_NONE; |
5042 in_frame_tree_ = true; | 5055 in_frame_tree_ = true; |
5043 | 5056 |
5044 // If this is the main frame going from a remote frame to a local frame, | 5057 // If this is the main frame going from a remote frame to a local frame, |
5045 // it needs to set RenderViewImpl's pointer for the main frame to itself | 5058 // it needs to set RenderViewImpl's pointer for the main frame to itself |
5046 // and ensure RenderWidget is no longer in swapped out mode. | 5059 // and ensure RenderWidget is no longer in swapped out mode. |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5283 // staying at about:blank. If this frame isn't in the map of unique names | 5296 // staying at about:blank. If this frame isn't in the map of unique names |
5284 // that have history items, or if it's staying at the initial about:blank URL, | 5297 // that have history items, or if it's staying at the initial about:blank URL, |
5285 // fall back to loading the default url. (We remove each name as we encounter | 5298 // fall back to loading the default url. (We remove each name as we encounter |
5286 // it, because it will only be used once as the frame is created.) | 5299 // it, because it will only be used once as the frame is created.) |
5287 if (info.isHistoryNavigationInNewChildFrame && is_content_initiated && | 5300 if (info.isHistoryNavigationInNewChildFrame && is_content_initiated && |
5288 frame_->parent()) { | 5301 frame_->parent()) { |
5289 // Check whether the browser has a history item for this frame that isn't | 5302 // Check whether the browser has a history item for this frame that isn't |
5290 // just staying at the initial about:blank document. | 5303 // just staying at the initial about:blank document. |
5291 bool should_ask_browser = false; | 5304 bool should_ask_browser = false; |
5292 RenderFrameImpl* parent = RenderFrameImpl::FromWebFrame(frame_->parent()); | 5305 RenderFrameImpl* parent = RenderFrameImpl::FromWebFrame(frame_->parent()); |
5293 const auto& iter = parent->history_subframe_unique_names_.find( | 5306 auto iter = parent->history_subframe_unique_names_.find( |
5294 frame_->uniqueName().utf8()); | 5307 unique_name_helper_.value()); |
5295 if (iter != parent->history_subframe_unique_names_.end()) { | 5308 if (iter != parent->history_subframe_unique_names_.end()) { |
5296 bool history_item_is_about_blank = iter->second; | 5309 bool history_item_is_about_blank = iter->second; |
5297 should_ask_browser = | 5310 should_ask_browser = |
5298 !history_item_is_about_blank || url != url::kAboutBlankURL; | 5311 !history_item_is_about_blank || url != url::kAboutBlankURL; |
5299 parent->history_subframe_unique_names_.erase(frame_->uniqueName().utf8()); | 5312 parent->history_subframe_unique_names_.erase(iter); |
5300 } | 5313 } |
5301 | 5314 |
5302 if (should_ask_browser) { | 5315 if (should_ask_browser) { |
5303 // Don't do this if |info| also says it is a client redirect, in which | 5316 // Don't do this if |info| also says it is a client redirect, in which |
5304 // case JavaScript on the page is trying to interrupt the history | 5317 // case JavaScript on the page is trying to interrupt the history |
5305 // navigation. | 5318 // navigation. |
5306 if (!info.isClientRedirect) { | 5319 if (!info.isClientRedirect) { |
5307 OpenURL(url, IsHttpPost(info.urlRequest), | 5320 OpenURL(url, IsHttpPost(info.urlRequest), |
5308 GetRequestBodyForWebURLRequest(info.urlRequest), | 5321 GetRequestBodyForWebURLRequest(info.urlRequest), |
5309 GetWebURLRequestHeaders(info.urlRequest), referrer, | 5322 GetWebURLRequestHeaders(info.urlRequest), referrer, |
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6849 // event target. Potentially a Pepper plugin will receive the event. | 6862 // event target. Potentially a Pepper plugin will receive the event. |
6850 // In order to tell whether a plugin gets the last mouse event and which it | 6863 // In order to tell whether a plugin gets the last mouse event and which it |
6851 // is, we set |pepper_last_mouse_event_target_| to null here. If a plugin gets | 6864 // is, we set |pepper_last_mouse_event_target_| to null here. If a plugin gets |
6852 // the event, it will notify us via DidReceiveMouseEvent() and set itself as | 6865 // the event, it will notify us via DidReceiveMouseEvent() and set itself as |
6853 // |pepper_last_mouse_event_target_|. | 6866 // |pepper_last_mouse_event_target_|. |
6854 pepper_last_mouse_event_target_ = nullptr; | 6867 pepper_last_mouse_event_target_ = nullptr; |
6855 #endif | 6868 #endif |
6856 } | 6869 } |
6857 | 6870 |
6858 } // namespace content | 6871 } // namespace content |
OLD | NEW |