From 86a49fc945d0dac666870d688a426fda36236cfa Mon Sep 17 00:00:00 2001 From: rramachandra Date: Sun, 15 Feb 2026 15:22:46 -0600 Subject: [PATCH] Simple reproduction of Blob url --- SampleApps/WebView2APISample/AppWindow.cpp | 7 +- .../ScenarioCustomDataPartition.cpp | 502 ++++++++++++++++++ .../ScenarioCustomDataPartition.h | 60 +++ .../WebView2APISample/WebView2APISample.rc | 1 + .../WebView2APISample.vcxproj | 11 + .../assets/ScenarioCustomDataPartition.html | 251 +++++++++ .../ScenarioCustomDataPartitionChild.html | 208 ++++++++ .../WebView2APISample/assets/Sir_CV_Raman.JPG | Bin 0 -> 21167 bytes SampleApps/WebView2APISample/resource.h | 1 + SampleApps/WebView2Samples.sln | 4 +- 10 files changed, 1042 insertions(+), 3 deletions(-) create mode 100644 SampleApps/WebView2APISample/ScenarioCustomDataPartition.cpp create mode 100644 SampleApps/WebView2APISample/ScenarioCustomDataPartition.h create mode 100644 SampleApps/WebView2APISample/assets/ScenarioCustomDataPartition.html create mode 100644 SampleApps/WebView2APISample/assets/ScenarioCustomDataPartitionChild.html create mode 100644 SampleApps/WebView2APISample/assets/Sir_CV_Raman.JPG diff --git a/SampleApps/WebView2APISample/AppWindow.cpp b/SampleApps/WebView2APISample/AppWindow.cpp index f692d5ce..aae3d6b5 100644 --- a/SampleApps/WebView2APISample/AppWindow.cpp +++ b/SampleApps/WebView2APISample/AppWindow.cpp @@ -32,6 +32,7 @@ #include "ScenarioAuthentication.h" #include "ScenarioClientCertificateRequested.h" #include "ScenarioCookieManagement.h" +#include "ScenarioCustomDataPartition.h" #include "ScenarioCustomDownloadExperience.h" #include "ScenarioCustomScheme.h" #include "ScenarioCustomSchemeNavigate.h" @@ -537,6 +538,11 @@ bool AppWindow::ExecuteWebViewCommands(WPARAM wParam, LPARAM lParam) NewComponent(this); return true; } + case IDM_SCENARIO_CUSTOM_DATA_PARTITION: + { + NewComponent(this); + return true; + } case IDM_SCENARIO_ADD_HOST_OBJECT: { NewComponent(this); @@ -2314,7 +2320,6 @@ void AppWindow::RegisterEventHandlers() { if (!m_shouldHandleNewWindowRequest) { - args->put_Handled(FALSE); return S_OK; } wil::com_ptr args_as_comptr = args; diff --git a/SampleApps/WebView2APISample/ScenarioCustomDataPartition.cpp b/SampleApps/WebView2APISample/ScenarioCustomDataPartition.cpp new file mode 100644 index 00000000..3bb7ee0f --- /dev/null +++ b/SampleApps/WebView2APISample/ScenarioCustomDataPartition.cpp @@ -0,0 +1,502 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "stdafx.h" + +#include "ScenarioCustomDataPartition.h" + +#include "AppWindow.h" +#include "CheckFailure.h" + +using namespace Microsoft::WRL; + +static constexpr WCHAR c_samplePath[] = L"ScenarioCustomDataPartition.html"; +static constexpr int c_minNewWindowSize = 100; +static constexpr WCHAR c_childWindowClassName[] = L"ScenarioCustomDataPartitionChildHostWindow"; + +static RECT GetPopupWindowRectFromUri(const std::wstring& uri) +{ + int left = 100; + int top = 100; + int width = 800; + int height = 600; + + if (uri.find(L"ScenarioCustomDataPartitionChild.html") != std::wstring::npos) + { + width = 600; + height = 800; + } + + if (width < c_minNewWindowSize) + { + width = c_minNewWindowSize; + } + if (height < c_minNewWindowSize) + { + height = c_minNewWindowSize; + } + + RECT rect = {left, top, left + width, top + height}; + return rect; +} + +bool ScenarioCustomDataPartition::EnsureChildWindowClassRegistered() +{ + static bool s_registered = false; + if (s_registered) + { + return true; + } + + WNDCLASSEXW windowClass = {}; + windowClass.cbSize = sizeof(WNDCLASSEXW); + windowClass.style = CS_HREDRAW | CS_VREDRAW; + windowClass.lpfnWndProc = ScenarioCustomDataPartition::ChildWndProcStatic; + windowClass.hInstance = GetModuleHandle(nullptr); + windowClass.hCursor = LoadCursor(nullptr, IDC_ARROW); + windowClass.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); + windowClass.lpszClassName = c_childWindowClassName; + + if (!RegisterClassExW(&windowClass)) + { + DWORD error = GetLastError(); + if (error != ERROR_CLASS_ALREADY_EXISTS) + { + return false; + } + } + + s_registered = true; + return true; +} + +LRESULT CALLBACK ScenarioCustomDataPartition::ChildWndProcStatic( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_NCCREATE) + { + auto* createStruct = reinterpret_cast(lParam); + auto* self = reinterpret_cast(createStruct->lpCreateParams); + SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(self)); + } + + auto* self = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (self) + { + return self->ChildWndProc(hWnd, message, wParam, lParam); + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +LRESULT ScenarioCustomDataPartition::ChildWndProc( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CLOSE: + CloseChildWindow(); + return 0; + case WM_SIZE: + ResizeChildWebView(); + break; + case WM_DESTROY: + if (hWnd == m_childWindow) + { + m_childWindow = nullptr; + m_childController = nullptr; + m_childWebView = nullptr; + } + break; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +void ScenarioCustomDataPartition::ResizeChildWebView() +{ + if (!m_childWindow || !m_childController) + { + return; + } + + RECT bounds = {}; + if (GetClientRect(m_childWindow, &bounds)) + { + CHECK_FAILURE(m_childController->put_Bounds(bounds)); + } +} + +void ScenarioCustomDataPartition::CloseChildWindow() +{ + if (m_childWebView && m_childWebMessageReceivedToken.value != 0) + { + m_childWebView->remove_WebMessageReceived(m_childWebMessageReceivedToken); + m_childWebMessageReceivedToken = {}; + } + + if (m_childController) + { + m_childController->Close(); + m_childController = nullptr; + } + m_childWebView = nullptr; + + if (m_childWindow) + { + HWND childWindow = m_childWindow; + m_childWindow = nullptr; + DestroyWindow(childWindow); + } +} + +ScenarioCustomDataPartition::ScenarioCustomDataPartition(AppWindow* appWindow) + : m_appWindow(appWindow), m_webView(appWindow->GetWebView()) +{ + m_sampleUri = m_appWindow->GetLocalUri(c_samplePath); + + // Disable host-level popup handling so this scenario can fully own NewWindowRequested. + m_appWindow->EnableHandlingNewWindowRequest(false); + + // Register event handlers + RegisterEventHandlers(); + + // Navigate to the sample page + CHECK_FAILURE(m_webView->Navigate(m_sampleUri.c_str())); +} + +void ScenarioCustomDataPartition::RegisterEventHandlers() +{ + // Turn off this scenario if we navigate away from the sample page + CHECK_FAILURE(m_webView->add_ContentLoading( + Callback( + [this](ICoreWebView2* sender, ICoreWebView2ContentLoadingEventArgs* args) -> HRESULT + { + wil::unique_cotaskmem_string uri; + sender->get_Source(&uri); + if (uri.get() != m_sampleUri) + { + m_appWindow->DeleteComponent(this); + } + return S_OK; + }) + .Get(), + &m_contentLoadingToken)); + + // Handle messages from the HTML UI + CHECK_FAILURE(m_webView->add_WebMessageReceived( + Callback( + [this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT + { + wil::unique_cotaskmem_string message; + CHECK_FAILURE(args->TryGetWebMessageAsString(&message)); + HandleWebMessage(message.get()); + return S_OK; + }) + .Get(), + &m_webMessageReceivedToken)); + + //! [CustomDataPartitionNewWindowRequested] + // Register a handler for the NewWindowRequested event. + // This handler captures child windows by creating them and setting partitions. + CHECK_FAILURE(m_webView->add_NewWindowRequested( + Callback( + [this](ICoreWebView2* sender, ICoreWebView2NewWindowRequestedEventArgs* args) -> HRESULT + { + // Get a deferral - we'll complete this asynchronously + wil::com_ptr deferral; + CHECK_FAILURE(args->GetDeferral(&deferral)); + + wil::com_ptr argsAsComPtr = args; + + if (m_childWindow || m_childController) + { + CloseChildWindow(); + } + + wil::unique_cotaskmem_string uri; + CHECK_FAILURE(args->get_Uri(&uri)); + std::wstring targetUri = uri.get() ? uri.get() : L""; + + RECT popupRect = GetPopupWindowRectFromUri(targetUri); + + if (!EnsureChildWindowClassRegistered()) + { + SendStatusToUI(L"Error: Failed to register child window class."); + CHECK_FAILURE(argsAsComPtr->put_Handled(FALSE)); + CHECK_FAILURE(deferral->Complete()); + return S_OK; + } + + m_childWindow = CreateWindowExW( + WS_EX_CONTROLPARENT, c_childWindowClassName, + L"Custom Data Partition Child Window", + WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, popupRect.left, + popupRect.top, popupRect.right - popupRect.left, + popupRect.bottom - popupRect.top, nullptr, nullptr, + GetModuleHandle(nullptr), this); + + if (!m_childWindow) + { + SendStatusToUI(L"Error: Failed to create child native window."); + CHECK_FAILURE(argsAsComPtr->put_Handled(FALSE)); + CHECK_FAILURE(deferral->Complete()); + return S_OK; + } + + ShowWindow(m_childWindow, SW_SHOWNORMAL); + UpdateWindow(m_childWindow); + + auto environment = m_appWindow->GetWebViewEnvironment(); + if (!environment) + { + SendStatusToUI(L"Error: WebView2 environment not available for child window."); + CloseChildWindow(); + CHECK_FAILURE(argsAsComPtr->put_Handled(FALSE)); + CHECK_FAILURE(deferral->Complete()); + return S_OK; + } + + CHECK_FAILURE(environment->CreateCoreWebView2Controller( + m_childWindow, + Callback( + [this, argsAsComPtr, deferral, targetUri]( + HRESULT result, ICoreWebView2Controller* controller) -> HRESULT + { + if (result == S_OK && controller) + { + m_childController = controller; + CHECK_FAILURE(m_childController->get_CoreWebView2(&m_childWebView)); + SetPartitionOnLastChild(L"DefaultPartitionForChild"); + CHECK_FAILURE(m_childWebView->add_WebMessageReceived( + Callback( + [this]( + ICoreWebView2* sender, + ICoreWebView2WebMessageReceivedEventArgs* args) + -> HRESULT + { + wil::unique_cotaskmem_string message; + CHECK_FAILURE(args->TryGetWebMessageAsString(&message)); + + if (std::wstring(message.get()) == L"getCustomPartition") + { + wil::com_ptr + webViewExperimental; + webViewExperimental = + m_childWebView.try_query< + ICoreWebView2Experimental20>(); + + if (!webViewExperimental) + { + SendStatusToChildUI( + L"Error: Custom partition API unavailable."); + return S_OK; + } + + wil::unique_cotaskmem_string partitionId; + HRESULT partitionHr = + webViewExperimental + ->get_CustomDataPartitionId(&partitionId); + + if (SUCCEEDED(partitionHr)) + { + if (partitionId.get() == nullptr || + wcslen(partitionId.get()) == 0) + { + SendStatusToChildUI( + L"Child partition: (default/none)"); + } + else + { + std::wstring status = + L"Child partition: '" + + std::wstring(partitionId.get()) + + L"'"; + SendStatusToChildUI(status); + } + } + else + { + SendStatusToChildUI( + L"Error: Failed to read child partition."); + } + } + + return S_OK; + }) + .Get(), + &m_childWebMessageReceivedToken)); + + auto childWebView3 = m_childWebView.try_query(); + if (childWebView3) + { + CHECK_FAILURE(childWebView3->SetVirtualHostNameToFolderMapping( + L"appassets.example", L"assets", + COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS)); + } + + ResizeChildWebView(); + CHECK_FAILURE(argsAsComPtr->put_NewWindow(m_childWebView.get())); + CHECK_FAILURE(argsAsComPtr->put_Handled(TRUE)); + if (!targetUri.empty()) + { + CHECK_FAILURE(m_childWebView->Navigate(targetUri.c_str())); + } + SendStatusToUI( + L"Child window created and captured! Ready to set partition."); + } + else + { + CloseChildWindow(); + SendStatusToUI( + L"Error: Failed to create child WebView controller."); + CHECK_FAILURE(argsAsComPtr->put_Handled(FALSE)); + } + + CHECK_FAILURE(deferral->Complete()); + return S_OK; + }) + .Get())); + + return S_OK; + }) + .Get(), + &m_newWindowRequestedToken)); + //! [CustomDataPartitionNewWindowRequested] +} + +void ScenarioCustomDataPartition::HandleWebMessage(const std::wstring& message) +{ + // Parse simple command messages from JavaScript + if (message.find(L"setPartition:") == 0) + { + // Extract partition ID from message + std::wstring partitionId = message.substr(13); // Skip "setPartition:" + SetPartitionOnLastChild(partitionId); + } + else if (message == L"checkPartition") + { + CheckCurrentPartition(); + } +} + +void ScenarioCustomDataPartition::SetPartitionOnLastChild(const std::wstring& partitionId) +{ + if (!m_childWebView) + { + SendStatusToUI(L"Error: No child window available. Create a child window first."); + return; + } + + //! [CustomDataPartitionSet] + // Try to set custom data partition using the experimental API + wil::com_ptr webViewExperimental; + webViewExperimental = m_childWebView.try_query(); + + if (!webViewExperimental) + { + SendStatusToUI(L"Error: Custom data partition API (ICoreWebView2Experimental20) not available in this WebView2 version."); + return; + } + + // Set the partition ID on the child window + HRESULT hr = webViewExperimental->put_CustomDataPartitionId(partitionId.c_str()); + //! [CustomDataPartitionSet] + + if (SUCCEEDED(hr)) + { + std::wstring status = L"✓ Success! Partition '" + partitionId + + L"' set on child window."; + SendStatusToUI(status); + } + else + { + SendStatusToUI(L"Error: Failed to set custom data partition."); + } +} + +void ScenarioCustomDataPartition::CheckCurrentPartition() +{ + //! [CustomDataPartitionGet] + // Check the partition of the parent window (should be empty/default) + wil::com_ptr webViewExperimental; + webViewExperimental = m_webView.try_query(); + + if (!webViewExperimental) + { + SendStatusToUI(L"Error: Custom data partition API not available."); + return; + } + + wil::unique_cotaskmem_string partitionId; + HRESULT hr = webViewExperimental->get_CustomDataPartitionId(&partitionId); + //! [CustomDataPartitionGet] + + if (SUCCEEDED(hr)) + { + if (partitionId.get() == nullptr || wcslen(partitionId.get()) == 0) + { + SendStatusToUI(L"✓ Parent window partition: (default/none) - Correct! Parent has no custom partition."); + } + else + { + std::wstring status = L"⚠ Parent window partition: '" + std::wstring(partitionId.get()) + + L"' (Note: Parent should typically remain in default partition)"; + SendStatusToUI(status); + } + } + else + { + SendStatusToUI(L"Error: Failed to get partition ID."); + } +} + +void ScenarioCustomDataPartition::SendStatusToUI(const std::wstring& status) +{ + // Send status message back to the HTML UI + // Escape single quotes in the status message + std::wstring escapedStatus = status; + size_t pos = 0; + while ((pos = escapedStatus.find(L"'", pos)) != std::wstring::npos) + { + escapedStatus.replace(pos, 1, L"\\'"); + pos += 2; + } + + std::wstring script = L"updateStatus('" + escapedStatus + L"');"; + CHECK_FAILURE(m_webView->ExecuteScript(script.c_str(), nullptr)); +} + +void ScenarioCustomDataPartition::SendStatusToChildUI(const std::wstring& status) +{ + if (!m_childWebView) + { + return; + } + + std::wstring escapedStatus = status; + size_t pos = 0; + while ((pos = escapedStatus.find(L"'", pos)) != std::wstring::npos) + { + escapedStatus.replace(pos, 1, L"\\'"); + pos += 2; + } + + std::wstring script = L"updateChildPartitionStatus('" + escapedStatus + L"');"; + CHECK_FAILURE(m_childWebView->ExecuteScript(script.c_str(), nullptr)); +} + +ScenarioCustomDataPartition::~ScenarioCustomDataPartition() +{ + // Restore default host-level popup handling. + if (m_appWindow) + { + m_appWindow->EnableHandlingNewWindowRequest(true); + } + + CloseChildWindow(); + + m_webView->remove_ContentLoading(m_contentLoadingToken); + m_webView->remove_WebMessageReceived(m_webMessageReceivedToken); + m_webView->remove_NewWindowRequested(m_newWindowRequestedToken); +} diff --git a/SampleApps/WebView2APISample/ScenarioCustomDataPartition.h b/SampleApps/WebView2APISample/ScenarioCustomDataPartition.h new file mode 100644 index 00000000..00cf23ca --- /dev/null +++ b/SampleApps/WebView2APISample/ScenarioCustomDataPartition.h @@ -0,0 +1,60 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once +#include "stdafx.h" + +#include + +#include "AppWindow.h" +#include "ComponentBase.h" + +// This component demonstrates custom data partition management for child windows. +// It shows how to: +// 1. Create child windows and capture them via NewWindowRequested event +// 2. Apply custom data partitions to child windows only (not parent) +// 3. Create blob URLs from images in the parent window +// 4. Test blob URL accessibility across partition boundaries +// +// Key pattern: In NewWindowRequested handler: +// 1. Get deferral +// 2. Create a native window for the popup +// 3. Create a WebView controller for that window +// 4. In controller-created callback, provide args->put_NewWindow(childWebView) +// 5. Complete deferral +class ScenarioCustomDataPartition : public ComponentBase +{ +public: + ScenarioCustomDataPartition(AppWindow* appWindow); + ~ScenarioCustomDataPartition() override; + static LRESULT CALLBACK ChildWndProcStatic( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +private: + AppWindow* m_appWindow = nullptr; + wil::com_ptr m_webView; + std::wstring m_sampleUri; + EventRegistrationToken m_contentLoadingToken = {}; + EventRegistrationToken m_webMessageReceivedToken = {}; + EventRegistrationToken m_newWindowRequestedToken = {}; + EventRegistrationToken m_childWebMessageReceivedToken = {}; + + // Track a single child popup window for partition management + HWND m_childWindow = nullptr; + wil::com_ptr m_childController; + wil::com_ptr m_childWebView; + + // Event handlers + LRESULT ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + static bool EnsureChildWindowClassRegistered(); + void CloseChildWindow(); + void ResizeChildWebView(); + + void RegisterEventHandlers(); + void HandleWebMessage(const std::wstring& message); + void SetPartitionOnLastChild(const std::wstring& partitionId); + void CheckCurrentPartition(); + void SendStatusToUI(const std::wstring& status); + void SendStatusToChildUI(const std::wstring& status); +}; diff --git a/SampleApps/WebView2APISample/WebView2APISample.rc b/SampleApps/WebView2APISample/WebView2APISample.rc index 5904d534..4ce69982 100644 --- a/SampleApps/WebView2APISample/WebView2APISample.rc +++ b/SampleApps/WebView2APISample/WebView2APISample.rc @@ -274,6 +274,7 @@ BEGIN MENUITEM "Shared worker WebResourceRequested", IDM_SCENARIO_SHARED_WORKER END MENUITEM "WebRTC UDP Port Configuration", IDM_SCENARIO_WEBRTC_UDP_PORT_CONFIGURATION + MENUITEM "Custom Data Partition for Child Windows", IDM_SCENARIO_CUSTOM_DATA_PARTITION POPUP "Custom Download Experience" BEGIN MENUITEM "Use Deferred Download Dialog", IDM_SCENARIO_USE_DEFERRED_DOWNLOAD diff --git a/SampleApps/WebView2APISample/WebView2APISample.vcxproj b/SampleApps/WebView2APISample/WebView2APISample.vcxproj index ec3c5d66..a4dfe8ab 100644 --- a/SampleApps/WebView2APISample/WebView2APISample.vcxproj +++ b/SampleApps/WebView2APISample/WebView2APISample.vcxproj @@ -231,6 +231,7 @@ + @@ -295,6 +296,7 @@ + @@ -380,6 +382,15 @@ $(OutDir)\assets + + $(OutDir)\assets + + + $(OutDir)\assets + + + $(OutDir)\assets + $(OutDir)\assets diff --git a/SampleApps/WebView2APISample/assets/ScenarioCustomDataPartition.html b/SampleApps/WebView2APISample/assets/ScenarioCustomDataPartition.html new file mode 100644 index 00000000..4a324d0a --- /dev/null +++ b/SampleApps/WebView2APISample/assets/ScenarioCustomDataPartition.html @@ -0,0 +1,251 @@ + + + + + + Custom Data Partition Sample + + + +

Custom Data Partition Sample

+ +
+ About this sample: This demonstrates how to create child windows and apply custom data partitions + to isolate storage. It also tests blob URL sharing across partition boundaries. +
+ + +
+

1. Create Child Window

+

Click the button to open the child page. The parent window captures it via the NewWindowRequested event.

+ +
+ + +
+

2. Set Custom Data Partition

+

Enter a partition ID and apply it to the most recently created child window. The parent window will never have a custom partition.

+ + + + +
+ Note: Only child windows should have custom partitions. The parent window remains in the default partition. + Click "Check Parent Window Partition" to verify the parent window has no custom partition set. +
+
+ + +
+

3. Blob URL Creation & Testing

+

This image is displayed in the parent window from assets. A blob URL will be created from it.

+ Sir C V Raman + + + + + + +
+ Test: Create a blob URL from the image, then try to access it from a partitioned child window + to observe cross-partition behavior. +
+
+ + +
+

Status

+
Ready. Click "Create Child Window" to begin.
+
+ + + + diff --git a/SampleApps/WebView2APISample/assets/ScenarioCustomDataPartitionChild.html b/SampleApps/WebView2APISample/assets/ScenarioCustomDataPartitionChild.html new file mode 100644 index 00000000..363de464 --- /dev/null +++ b/SampleApps/WebView2APISample/assets/ScenarioCustomDataPartitionChild.html @@ -0,0 +1,208 @@ + + + + + + Custom Data Partition Child Window + + + +

Custom Data Partition Child Window

+ +
+

This is the dedicated child window page opened by window.open() from the parent scenario page.

+

The parent app captures this window in NewWindowRequested, then you can apply a custom partition from the parent UI.

+
+ +
+ Keep this child window open while setting partition IDs in the parent window. +
+ +
+

Blob URL Image Test

+

Paste a blob URL from the parent window and try loading it here.

+ +
+ + + +
+
Waiting for blob URL input.
+ Blob URL image preview +
+ +
+

Custom Partition

+

Query the child window's current custom data partition from native code.

+ + +
Waiting to query partition.
+
+ +
+

Local Storage Test

+

Use key currentTime to verify storage behavior across partitions.

+ + +
Waiting to test local storage.
+
+ + + + diff --git a/SampleApps/WebView2APISample/assets/Sir_CV_Raman.JPG b/SampleApps/WebView2APISample/assets/Sir_CV_Raman.JPG new file mode 100644 index 0000000000000000000000000000000000000000..5c302e8c573f64b35069ba6ec7c31816fb9005db GIT binary patch literal 21167 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 wx^3s(u3(@UK^;