| OLD | NEW |
| 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 #import "ios/web/net/clients/crw_js_injection_network_client.h" | 5 #import "ios/web/net/clients/crw_js_injection_network_client.h" |
| 6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
| 7 #include "base/logging.h" | 10 #include "base/logging.h" |
| 8 #include "base/mac/objc_property_releaser.h" | 11 #include "base/mac/objc_property_releaser.h" |
| 9 #include "base/mac/scoped_nsobject.h" | 12 #include "base/mac/scoped_nsobject.h" |
| 10 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 11 #import "ios/net/crn_http_url_response.h" | 14 #import "ios/net/crn_http_url_response.h" |
| 12 #import "ios/third_party/blink/src/html_tokenizer.h" | 15 #import "ios/third_party/blink/src/html_tokenizer.h" |
| 13 | 16 |
| 14 // CRWJSInjectionNetworkClient injects an external script tag reference for | 17 // CRWJSInjectionNetworkClient injects an external script tag reference for |
| 15 // crweb.js into HTML and XHTML documents. To do this correctly, three data | 18 // crweb.js into HTML and XHTML documents. To do this correctly, three data |
| 16 // points are needed: where to inject the script tag, what encoding the content | 19 // points are needed: where to inject the script tag, what encoding the content |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 | 357 |
| 355 - (void)sendInjectedResponseIfNeeded { | 358 - (void)sendInjectedResponseIfNeeded { |
| 356 if (!_proceedWithInjection) | 359 if (!_proceedWithInjection) |
| 357 return; | 360 return; |
| 358 | 361 |
| 359 NSData* firstData = [_pendingData firstObject]; | 362 NSData* firstData = [_pendingData firstObject]; |
| 360 NSUInteger dataLength = [firstData length]; | 363 NSUInteger dataLength = [firstData length]; |
| 361 if (!dataLength) | 364 if (!dataLength) |
| 362 return; | 365 return; |
| 363 | 366 |
| 364 const uint8* bytes = reinterpret_cast<const uint8*>([firstData bytes]); | 367 const uint8_t* bytes = reinterpret_cast<const uint8_t*>([firstData bytes]); |
| 365 | 368 |
| 366 // Construct one data in which to send the content + injected script tag. | 369 // Construct one data in which to send the content + injected script tag. |
| 367 base::scoped_nsobject<NSMutableData> combined([[NSMutableData alloc] init]); | 370 base::scoped_nsobject<NSMutableData> combined([[NSMutableData alloc] init]); |
| 368 if (_byteOffsetAtWhichToInject) | 371 if (_byteOffsetAtWhichToInject) |
| 369 [combined appendBytes:static_cast<const void*>(bytes) | 372 [combined appendBytes:static_cast<const void*>(bytes) |
| 370 length:_byteOffsetAtWhichToInject]; | 373 length:_byteOffsetAtWhichToInject]; |
| 371 | 374 |
| 372 // Send back the JavaScript content to inject. | 375 // Send back the JavaScript content to inject. |
| 373 [combined appendData:[self jsInjectionContent]]; | 376 [combined appendData:[self jsInjectionContent]]; |
| 374 [combined | 377 [combined |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 // Get some data to investigate. | 457 // Get some data to investigate. |
| 455 NSData* firstData = [_pendingData firstObject]; | 458 NSData* firstData = [_pendingData firstObject]; |
| 456 if (!firstData && [firstData length] < kMinimumBytesNeededForBOM) { | 459 if (!firstData && [firstData length] < kMinimumBytesNeededForBOM) { |
| 457 NOTREACHED(); | 460 NOTREACHED(); |
| 458 return; | 461 return; |
| 459 } | 462 } |
| 460 | 463 |
| 461 // Do the same check that WebKit does for the byte order mark (BOM), which | 464 // Do the same check that WebKit does for the byte order mark (BOM), which |
| 462 // must be right at the beginning of the content to be accepted. | 465 // must be right at the beginning of the content to be accepted. |
| 463 // Info on byte order mark: http://en.wikipedia.org/wiki/Byte_order_mark | 466 // Info on byte order mark: http://en.wikipedia.org/wiki/Byte_order_mark |
| 464 const uint8* bytes = reinterpret_cast<const uint8*>([firstData bytes]); | 467 const uint8_t* bytes = reinterpret_cast<const uint8_t*>([firstData bytes]); |
| 465 if (BytesEqual(bytes, 0xFF, 0xFE)) { | 468 if (BytesEqual(bytes, 0xFF, 0xFE)) { |
| 466 bytes += 2; | 469 bytes += 2; |
| 467 | 470 |
| 468 if (!BytesEqual(bytes, 0x00, 0x00)) { | 471 if (!BytesEqual(bytes, 0x00, 0x00)) { |
| 469 _contentEncoding = NSUTF16LittleEndianStringEncoding; | 472 _contentEncoding = NSUTF16LittleEndianStringEncoding; |
| 470 _headerLength += 2; | 473 _headerLength += 2; |
| 471 } else { | 474 } else { |
| 472 _contentEncoding = NSUTF32LittleEndianStringEncoding; | 475 _contentEncoding = NSUTF32LittleEndianStringEncoding; |
| 473 _headerLength += 4; | 476 _headerLength += 4; |
| 474 } | 477 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 NSData* firstData = [_pendingData firstObject]; | 518 NSData* firstData = [_pendingData firstObject]; |
| 516 if (!firstData && [firstData length] < kMinimumBytesNeededForXMLDecl) { | 519 if (!firstData && [firstData length] < kMinimumBytesNeededForXMLDecl) { |
| 517 NOTREACHED(); | 520 NOTREACHED(); |
| 518 return; | 521 return; |
| 519 } | 522 } |
| 520 | 523 |
| 521 // Do the same check that WebKit does for an XML declaration. The XML spec | 524 // Do the same check that WebKit does for an XML declaration. The XML spec |
| 522 // is not exactly clear about what, if anything, can appear before an XML | 525 // is not exactly clear about what, if anything, can appear before an XML |
| 523 // declaration. Can there be white space? Can there be comments? WebKit only | 526 // declaration. Can there be white space? Can there be comments? WebKit only |
| 524 // accepts XML declarations if they are right at the beginning of the content. | 527 // accepts XML declarations if they are right at the beginning of the content. |
| 525 const uint8* bytes = reinterpret_cast<const uint8*>([firstData bytes]); | 528 const uint8_t* bytes = reinterpret_cast<const uint8_t*>([firstData bytes]); |
| 526 if (BytesEqual(bytes, '<', '?', 'x', 'm', 'l')) { | 529 if (BytesEqual(bytes, '<', '?', 'x', 'm', 'l')) { |
| 527 _contentEncoding = NSISOLatin1StringEncoding; | 530 _contentEncoding = NSISOLatin1StringEncoding; |
| 528 } else if (BytesEqual(bytes, '<', 0, '?', 0, 'x', 0)) { | 531 } else if (BytesEqual(bytes, '<', 0, '?', 0, 'x', 0)) { |
| 529 _contentEncoding = NSUTF16LittleEndianStringEncoding; | 532 _contentEncoding = NSUTF16LittleEndianStringEncoding; |
| 530 } else if (BytesEqual(bytes, 0, '<', 0, '?', 0, 'x')) { | 533 } else if (BytesEqual(bytes, 0, '<', 0, '?', 0, 'x')) { |
| 531 _contentEncoding = NSUTF16BigEndianStringEncoding; | 534 _contentEncoding = NSUTF16BigEndianStringEncoding; |
| 532 } else if (BytesEqual(bytes, '<', 0, 0, 0, '?', 0, 0, 0)) { | 535 } else if (BytesEqual(bytes, '<', 0, 0, 0, '?', 0, 0, 0)) { |
| 533 _contentEncoding = NSUTF32LittleEndianStringEncoding; | 536 _contentEncoding = NSUTF32LittleEndianStringEncoding; |
| 534 } else if (BytesEqual(bytes, 0, 0, 0, '<', 0, 0, 0, '?')) { | 537 } else if (BytesEqual(bytes, 0, 0, 0, '<', 0, 0, 0, '?')) { |
| 535 _contentEncoding = NSUTF32BigEndianStringEncoding; | 538 _contentEncoding = NSUTF32BigEndianStringEncoding; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 558 // It's possible that the server returned data in small chunks, so coalesce | 561 // It's possible that the server returned data in small chunks, so coalesce |
| 559 // the data into one buffer if needed. Try pooling everything into one chunk | 562 // the data into one buffer if needed. Try pooling everything into one chunk |
| 560 // that meets the limit of what we look at. | 563 // that meets the limit of what we look at. |
| 561 [self coalesceDataIfNeeded:kLimitOfBytesToCheckForHeadTag]; | 564 [self coalesceDataIfNeeded:kLimitOfBytesToCheckForHeadTag]; |
| 562 | 565 |
| 563 // Get some data to investigate. Of course we need at least | 566 // Get some data to investigate. Of course we need at least |
| 564 // kMinimumBytesNeededForHTMLTag bytes to do the investigation. | 567 // kMinimumBytesNeededForHTMLTag bytes to do the investigation. |
| 565 NSData* firstData = [_pendingData firstObject]; | 568 NSData* firstData = [_pendingData firstObject]; |
| 566 DCHECK([firstData length] >= kMinimumBytesNeededForHTMLTag); | 569 DCHECK([firstData length] >= kMinimumBytesNeededForHTMLTag); |
| 567 | 570 |
| 568 const uint8* bytes8 = reinterpret_cast<const uint8*>([firstData bytes]); | 571 const uint8_t* bytes8 = reinterpret_cast<const uint8_t*>([firstData bytes]); |
| 569 | 572 |
| 570 WebCore::CharacterProvider provider; | 573 WebCore::CharacterProvider provider; |
| 571 switch (_contentEncoding) { | 574 switch (_contentEncoding) { |
| 572 case NSUTF16BigEndianStringEncoding: | 575 case NSUTF16BigEndianStringEncoding: |
| 573 case NSUTF16LittleEndianStringEncoding: | 576 case NSUTF16LittleEndianStringEncoding: |
| 574 case NSUTF32BigEndianStringEncoding: | 577 case NSUTF32BigEndianStringEncoding: |
| 575 case NSUTF32LittleEndianStringEncoding: { | 578 case NSUTF32LittleEndianStringEncoding: { |
| 576 const uint16* bytes16 = | 579 const uint16_t* bytes16 = |
| 577 reinterpret_cast<const uint16*>(bytes8 + _headerLength); | 580 reinterpret_cast<const uint16_t*>(bytes8 + _headerLength); |
| 578 | 581 |
| 579 provider.setContents(bytes16, [firstData length] - _headerLength); | 582 provider.setContents(bytes16, [firstData length] - _headerLength); |
| 580 | 583 |
| 581 if (_contentEncoding == NSUTF16LittleEndianStringEncoding || | 584 if (_contentEncoding == NSUTF16LittleEndianStringEncoding || |
| 582 _contentEncoding == NSUTF32LittleEndianStringEncoding) | 585 _contentEncoding == NSUTF32LittleEndianStringEncoding) |
| 583 provider.setLittleEndian(); | 586 provider.setLittleEndian(); |
| 584 break; | 587 break; |
| 585 } | 588 } |
| 586 | 589 |
| 587 default: { | 590 default: { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 } | 627 } |
| 625 } | 628 } |
| 626 | 629 |
| 627 // There is an early exit case right at the end of the start-tag from the | 630 // There is an early exit case right at the end of the start-tag from the |
| 628 // WebCore::HTMLTokenizer::nextToken(), so double check to see if we hit | 631 // WebCore::HTMLTokenizer::nextToken(), so double check to see if we hit |
| 629 // the limit. | 632 // the limit. |
| 630 [self checkIfByteLimitPassed:provider]; | 633 [self checkIfByteLimitPassed:provider]; |
| 631 } | 634 } |
| 632 | 635 |
| 633 @end | 636 @end |
| OLD | NEW |