lvsti / CEF.swift

Swift bindings for the Chromium Embedded Framework
BSD 3-Clause "New" or "Revised" License
94 stars 29 forks source link

CEFResourceHandler does not seem to work as expected #54

Closed ebaujard closed 3 years ago

ebaujard commented 3 years ago

Hi, I have a problem with CEFResourceHandler in branch cef_4280. The bufferLength parameter is not set correctly for onReadResponseData.

class TestResourceHandler: CEFResourceHandler { var fileData:Data? var bytesDone:Int = 0

func onOpenResponseStream(request: CEFRequest, callback: CEFCallback) -> CEFOnOpenResponseStreamAction {
    let fileManager = FileManager.default
    var filePath = Bundle.main.resourcePath!
    let url = request.url!.absoluteString
    let index = url.index(url.startIndex, offsetBy: "http://localhost".characters.count)

    filePath += url.substring(from:index)
    if fileManager.fileExists(atPath: filePath) {
        // Open the file
        let file = FileHandle(forReadingAtPath: filePath)
        fileData = file?.readDataToEndOfFile()
        // Close the file
        file?.closeFile()
    } else {
        print("File not found : " + filePath)
    }
    return .handle
}

func onGetResponseHeaders(response: CEFResponse) -> CEFOnGetResponseHeadersAction {
    if fileData != nil{
        response.status = 200;
        response.statusText = "OK";
        return .continueWithResponseLength(UInt64(fileData!.count)) // Here value = 96
    }
    return .abort
}

func onReadResponseData(buffer: UnsafeMutableRawPointer, bufferLength: Int, callback: CEFResourceReadCallback) -> CEFOnReadResponseDataAction {
   // Here bufferLength = 65536 expected -> 96
    let nsData = fileData! as NSData
    buffer.copyMemory(from: nsData.bytes.advanced(by: bytesDone), byteCount: bufferLength)
    bytesDone += bufferLength
    if bytesDone == UInt64(fileData!.count) {
        return .complete
    } else {
        return .read(bufferLength)
    }
}

}

Did I forget something? Do you have an example of use?

Thanks

lvsti commented 3 years ago

Hi, the bufferLength parameter is called so for a reason, it won't contain the response length you set before but the size of the buffer allocated by CEF and provided in the first parameter. This function may be called repeatedly for subsequent chunks of the response data. It's your responsibility to keep track of both the response data length (as simple as fileData.count) and the offset (as you did with bytesDone). Basically just copy let chunkSize = min(fileData.count - bytesDone, bufferLength) bytes to buffer, then do bytesDone += chunkSize and return .read(chunkSize)

ebaujard commented 3 years ago

Hi, Thank you for your prompt answer. I'm migrating from CEF 2924 to CEF 4280, it's disturbing to have the same parameter in these 2 versions with a different purpose.