|
|
Chromium Code Reviews
DescriptionMHTML: Allows 'data:' URLs to be processed using normal request processing.
An alternative of allowing Blink to parse data URLs for all content-types
was considered, but this breaks behavior elsewhere in blink that requires
fonts defined in 'data:' URLs but not referenced never be decoded.
Instead, we stop sandboxing requests for 'data:' URLs and allow them to
use the normal request machinery.
BUG=647122
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel
Committed: https://crrev.com/4204367ed53fb3ba794678d78e7d4fc149f17787
Cr-Commit-Position: refs/heads/master@{#420365}
Patch Set 1 #
Total comments: 3
Patch Set 2 : add an expectation #Patch Set 3 : git squash commit. #Patch Set 4 : Adds a rebaseline line to test expectations. #
Messages
Total messages: 56 (36 generated)
The CQ bit was checked by dewittj@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
dewittj@chromium.org changed reviewers: + dimich@chromium.org
ptal, generating baselines now.
The CQ bit was checked by dewittj@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was checked by dewittj@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,win7_blink_compile_dbg,win7_blink_compile_rel,win7_blink_rel,linux_blink_rel ==========
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,win7_blink_compile_dbg,win7_blink_compile_rel,win7_blink_rel,linux_blink_rel ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,win7_blink_compile_dbg,win7_blink_compile_rel,win7_blink_rel,linux_precise_blink_rel ==========
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,win7_blink_compile_dbg,win7_blink_compile_rel,win7_blink_rel,linux_precise_blink_rel ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel ==========
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... File third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp (right): https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp:450: // Abort the request if the archive doesn't contain the resource, except I still feel the resourceForStaticData should succeed in this case. I think not loading fonts before they are used is stemming from the desire to avoid actual network load of large fornts that are mentioned by URL in the stylesheet. There are stylesheets out there that are listing a bunch of font resources by URL but the page ends up using one or none etc. In those scenarios, we should avoid loading. As for fonts present in archive as data: URLs, they are already here and it doesn't make much sense to differentiate them from say images in the same archive. Lets discuss a bit offline, perhaps I'm missing something.
dewittj@chromium.org changed reviewers: + japhet@chromium.org
https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... File third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp (right): https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp:450: // Abort the request if the archive doesn't contain the resource, except On 2016/09/19 19:54:16, Dmitry Titov wrote: > I still feel the resourceForStaticData should succeed in this case. I think not > loading fonts before they are used is stemming from the desire to avoid actual > network load of large fornts that are mentioned by URL in the stylesheet. There > are stylesheets out there that are listing a bunch of font resources by URL but > the page ends up using one or none etc. In those scenarios, we should avoid > loading. > > As for fonts present in archive as data: URLs, they are already here and it > doesn't make much sense to differentiate them from say images in the same > archive. > > Lets discuss a bit offline, perhaps I'm missing something. The CSS spec says that fonts should not be "downloaded" unless referenced: https://www.w3.org/TR/css-fonts-3/#font-face-loading Chrome seems to interpret that as not processing the font - no exceptions etc - until the font is referenced. There is a test that checks this behavior for fonts specified as data: URLs. It would be better if resourceForStaticData could return a resource that'd finish loading asynchronously. Today it calls finish() directly, which is what triggers the console exception. I believe that if we just fall through to createResourceForLoading, we will use the net stack to decode and finish the font resource loading, which implies the desired async behavior. +japhet - do you have an opinion on how we should enforce font async loading, while being certain that archives never can access the actual network?
dewittj@chromium.org changed reviewers: + jianli@chromium.org
+jianli for context
lgtm, this seem to provide desired behavior. Defer to Nate for potential refactor ideas though.
LGTM if you agree that my wild idea below is worse than the alternatives :) https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... File third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp (right): https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp:450: // Abort the request if the archive doesn't contain the resource, except On 2016/09/20 22:44:55, dewittj wrote: > On 2016/09/19 19:54:16, Dmitry Titov wrote: > > I still feel the resourceForStaticData should succeed in this case. I think > not > > loading fonts before they are used is stemming from the desire to avoid actual > > network load of large fornts that are mentioned by URL in the stylesheet. > There > > are stylesheets out there that are listing a bunch of font resources by URL > but > > the page ends up using one or none etc. In those scenarios, we should avoid > > loading. > > > > As for fonts present in archive as data: URLs, they are already here and it > > doesn't make much sense to differentiate them from say images in the same > > archive. > > > > Lets discuss a bit offline, perhaps I'm missing something. > > The CSS spec says that fonts should not be "downloaded" unless referenced: > https://www.w3.org/TR/css-fonts-3/#font-face-loading > > Chrome seems to interpret that as not processing the font - no exceptions etc - > until the font is referenced. There is a test that checks this behavior for > fonts specified as data: URLs. > > It would be better if resourceForStaticData could return a resource that'd > finish loading asynchronously. Today it calls finish() directly, which is what > triggers the console exception. > > I believe that if we just fall through to createResourceForLoading, we will use > the net stack to decode and finish the font resource loading, which implies the > desired async behavior. > > +japhet - do you have an opinion on how we should enforce font async loading, > while being certain that archives never can access the actual network? What if resourceForStaticData() checks resourceNeedsLoad(), and if it returns false, creates the Resource* but doesn't initialize it? I don't know if that will catch any cases besides data: urls, but assuming it was data: urls only, then you could just have startLoad() check whether this is a data: url and do the parse. That requires refactoring resourceForStaticData() a bunch, though, as you'd need to pull populating the Resource into a helper. Having written this idea out, I'm not skeptical that it's cleaner than what you have here.
On 2016/09/21 19:30:02, Nate Chapin wrote: > LGTM if you agree that my wild idea below is worse than the alternatives :) > > https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... > File third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp (right): > > https://codereview.chromium.org/2346293002/diff/1/third_party/WebKit/Source/c... > third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp:450: // Abort the > request if the archive doesn't contain the resource, except > On 2016/09/20 22:44:55, dewittj wrote: > > On 2016/09/19 19:54:16, Dmitry Titov wrote: > > > I still feel the resourceForStaticData should succeed in this case. I think > > not > > > loading fonts before they are used is stemming from the desire to avoid > actual > > > network load of large fornts that are mentioned by URL in the stylesheet. > > There > > > are stylesheets out there that are listing a bunch of font resources by URL > > but > > > the page ends up using one or none etc. In those scenarios, we should avoid > > > loading. > > > > > > As for fonts present in archive as data: URLs, they are already here and it > > > doesn't make much sense to differentiate them from say images in the same > > > archive. > > > > > > Lets discuss a bit offline, perhaps I'm missing something. > > > > The CSS spec says that fonts should not be "downloaded" unless referenced: > > https://www.w3.org/TR/css-fonts-3/#font-face-loading > > > > Chrome seems to interpret that as not processing the font - no exceptions etc > - > > until the font is referenced. There is a test that checks this behavior for > > fonts specified as data: URLs. > > > > It would be better if resourceForStaticData could return a resource that'd > > finish loading asynchronously. Today it calls finish() directly, which is > what > > triggers the console exception. > > > > I believe that if we just fall through to createResourceForLoading, we will > use > > the net stack to decode and finish the font resource loading, which implies > the > > desired async behavior. > > > > +japhet - do you have an opinion on how we should enforce font async loading, > > while being certain that archives never can access the actual network? > > What if resourceForStaticData() checks resourceNeedsLoad(), and if it returns > false, creates the Resource* but doesn't initialize it? I don't know if that > will catch any cases besides data: urls, but assuming it was data: urls only, > then you could just have startLoad() check whether this is a data: url and do > the parse. That requires refactoring resourceForStaticData() a bunch, though, as > you'd need to pull populating the Resource into a helper. > > Having written this idea out, I'm not skeptical that it's cleaner than what you > have here. s/not/now
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_dbg,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ==========
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_dbg,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_dbg,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ==========
The CQ bit was checked by dewittj@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: ios-device on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/ios-device/builds...) ios-simulator on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/ios-simulator/bui...) mac_chromium_rel_ng on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/mac_chromium_rel_...)
The CQ bit was checked by dewittj@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
I think your idea has merit, but the code is complicated enough that I'm not certain I'd get everything right on the first go. So let's land this and then look at other ways to achieve the desired result.
The CQ bit was unchecked by dewittj@chromium.org
The CQ bit was checked by dewittj@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from japhet@chromium.org, dimich@chromium.org Link to the patchset: https://codereview.chromium.org/2346293002/#ps40001 (title: "git squash commit.")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: linux_android_rel_ng on master.tryserver.chromium.android (JOB_FAILED, https://build.chromium.org/p/tryserver.chromium.android/builders/linux_androi...)
The CQ bit was checked by dewittj@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
There were warnings when CQ was processing your CL: * CQ is not running the win7_blink_dbg trybot, per your CQ_INCLUDE_TRYBOTS flag request. That bot was already specified, with these tests: ['defaulttests']
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: mac_chromium_rel_ng on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/mac_chromium_rel_...)
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_dbg,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ==========
The CQ bit was checked by dewittj@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from japhet@chromium.org, dimich@chromium.org Link to the patchset: https://codereview.chromium.org/2346293002/#ps60001 (title: "Adds a rebaseline line to test expectations.")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Message was sent while issue was closed.
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ==========
Message was sent while issue was closed.
Committed patchset #4 (id:60001)
Message was sent while issue was closed.
Description was changed from ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel ========== to ========== MHTML: Allows 'data:' URLs to be processed using normal request processing. An alternative of allowing Blink to parse data URLs for all content-types was considered, but this breaks behavior elsewhere in blink that requires fonts defined in 'data:' URLs but not referenced never be decoded. Instead, we stop sandboxing requests for 'data:' URLs and allow them to use the normal request machinery. BUG=647122 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:win7_blink_dbg,linux_precise_blink_rel,linux_precise_blink_dbg,mac10.9_blink_dbg,mac10.9_blink_rel,win7_blink_rel,mac10.10_blink_rel,mac10.11_blink_rel,mac10.11_retina_blink_rel,win10_blink_rel,linux_trusty_blink_rel Committed: https://crrev.com/4204367ed53fb3ba794678d78e7d4fc149f17787 Cr-Commit-Position: refs/heads/master@{#420365} ==========
Message was sent while issue was closed.
Patchset 4 (id:??) landed as https://crrev.com/4204367ed53fb3ba794678d78e7d4fc149f17787 Cr-Commit-Position: refs/heads/master@{#420365} |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
